IntegrityError at /accounts/signup/ NOT NULL constraint failed: users_user.birth_date in Django allauth form

IntegrityError at /accounts/signup/ NOT NULL constraint failed: users_user.birth_date in Django allauth form

当我尝试使用带有自定义用户模型的 Django allauth 表单注册时出现以下错误。

IntegrityError at /accounts/signup/
NOT NULL constraint failed: users_user.birth_date

这是我使用的自定义用户模型及其管理器:

from django.contrib.auth.models import AbstractUser, BaseUserManager ## A new class is imported. ##
from django.db import models
from datetime import datetime

class UserManager(BaseUserManager):
    """Model manager for User model with no username field."""

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """Make and save a User with the given email and password."""
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        """Make and save a regular User with the given email and password."""
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        """Make and save a SuperUser with the given email and password."""
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)

    
# User model
class User(AbstractUser):
    """User model."""

    username = None
    email = models.EmailField(verbose_name='email address', unique=True)

    first_name = models.CharField(max_length=128, blank=False)
    last_name = models.CharField(max_length=128, blank=False)
    profession_title = models.CharField(max_length=128, blank=False)

    country = models.CharField(max_length=32, blank=False)
    city = models.CharField(max_length=64, blank=False)
    postal_code = models.CharField(max_length=24, blank=False)
    address = models.CharField(max_length=255, blank=False)

    workplace = models.CharField(max_length=128, blank=False)
    phone_nr = models.CharField(max_length=32, blank=False)
    birth_date = models.DateField(null=False, blank=True)
    
    email_verified = models.BooleanField(default=False) # email verified
    activation_key = models.CharField(max_length=64)
    key_expires = models.DateTimeField(blank=False, default=datetime.now())





    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'profession_title',
                        'country', 'city', 'postal_code','address',
                        'workplace', 'phone_nr', 'birth_date'] 
                        # Email & Password are required by default.


    @property
    def is_email_verified(self):
        "Is the user email verified?"
        return self.email_verified

这是我使用的表格:

class CustomSignupForm(SignupForm):
    first_name = forms.CharField(label='First name', widget=forms.TextInput, required=True, max_length=128)
    last_name = forms.CharField(label='Last name', widget=forms.TextInput, required=True, max_length=128)
    profession_title = forms.CharField(label='Profession name', widget=forms.TextInput, required=True, max_length=128)

    country = forms.CharField(label='Country', widget=forms.TextInput, required=True, max_length=32)
    city = forms.CharField(label='City', widget=forms.TextInput, required=True, max_length=64)
    postal_code =  forms.CharField(label='Postal code', widget=forms.TextInput, required=True, max_length=24)
    address =  forms.CharField(label='Address', widget=forms.TextInput, required=True, max_length=255)
    
    workplace =  forms.CharField(label='Workplace', widget=forms.TextInput, required=True, max_length=128)
    phone_nr =  forms.CharField(label='Phone number', widget=forms.TextInput, required=True, max_length=32)
    birth_date = forms.DateField(label='Birth date', widget=forms.SelectDateWidget(years=range(1900, datetime.now().year)), required=True)


    is_staff = forms.BooleanField(label='Is admin?', widget=forms.CheckboxInput, required=False)


    def __init__(self, *args, **kwargs):
        super(CustomSignupForm, self).__init__(*args, **kwargs)
        del self.fields['password2']
        del self.fields['password1']

    def signup(self, request, user):
        self.cleaned_data['password1'] = 'unknown'

        print("Birth date", self.cleaned_data['birth_date'])

        user = super(CustomSignupForm, self).save(commit=False)

        password = User.objects.make_random_password()
        user.set_password(password)
        user.save()
        return user

    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 
                'profession_title','country', 'city', 'postal_code','address',
                'is_staff','workplace', 'phone_nr', 'birth_date',)

我收到的错误消息如下所示:

Quit the server with CONTROL-C.
[28/Mar/2022 13:31:57] "GET / HTTP/1.1" 200 1301
[28/Mar/2022 13:31:59] "GET /accounts/login/ HTTP/1.1" 200 1348
[28/Mar/2022 13:32:01] "GET /accounts/signup/ HTTP/1.1" 200 8241
/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1534: RuntimeWarning: DateTimeField User.key_expires received a naive datetime (2022-03-28 13:31:53.714715) while time zone support is active.
  warnings.warn(
Internal Server Error: /accounts/signup/
Traceback (most recent call last):
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: users_user.birth_date

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/views/generic/base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/decorators.py", line 20, in wrap
    resp = function(request, *args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/views/decorators/debug.py", line 92, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/account/views.py", line 234, in dispatch
    return super(SignupView, self).dispatch(request, *args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/account/views.py", line 77, in dispatch
    response = super(RedirectAuthenticatedUserMixin, self).dispatch(
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/account/views.py", line 207, in dispatch
    return super(CloseableSignupMixin, self).dispatch(request, *args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/views/generic/base.py", line 119, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/account/views.py", line 105, in post
    response = self.form_valid(form)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/account/views.py", line 250, in form_valid
    self.user = form.save(self.request)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/account/forms.py", line 423, in save
    adapter.save_user(request, user, self)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/allauth/account/adapter.py", line 250, in save_user
    user.save()
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/contrib/auth/base_user.py", line 68, in save
    super().save(*args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/base.py", line 806, in save
    self.save_base(
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/base.py", line 857, in save_base
    updated = self._save_table(
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/base.py", line 1000, in _save_table
    results = self._do_insert(
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/base.py", line 1041, in _do_insert
    return manager._insert(
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/query.py", line 1434, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1621, in execute_sql
    cursor.execute(sql, params)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 103, in execute
    return super().execute(sql, params)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/home/asdf/python-projects/medimageshub/.venv/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: users_user.birth_date
[28/Mar/2022 13:32:06] "POST /accounts/signup/ HTTP/1.1" 500 219583

birth_date 应该是数据库中的必填字段。

我试着在 user.save 之前分配 birth_date 就像 这个:

def signup(self, request, user):
    self.cleaned_data['password1'] = 'unknown'

    print("Birth date", self.cleaned_data['birth_date'])

    user = super(CustomSignupForm, self).save(commit=False)

    password = User.objects.make_random_password()
    user.set_password(password)
    user.birth_date = self.cleaned_data['birth_date']
    user.save()
    return user

但我仍然得到同样的错误。

仅当我从 table 中删除“birth_date”并迁移时它才得到修复。但这不是我想要的解决方案,因为我想要一个 birth_date 字段,这是必需的。

我尝试调试,但我看不到 cleaned_data 集合中的内容。 我不明白为什么会出现此错误。

如何修复此错误?

似乎由于您在用户 class 中设置 birth_date 属性的方式而引发此错误。您设置了 null=Falseblank=True,所以我假设 NOT NULL 约束失败,因为您试图将字段设置为 None,而由于 blank=True 而不允许这样做.我建议在您对 birth_date 的定义中删除一个或另一个,但如果能看到 cleaned data 里面的内容,就可以知道传递给 Django 的到底是什么。

我找到原因了。一开始我以为它保存了所有其他数据,但事实并非如此。它不保存任何数据。我在网上遵循了一些 allauth 指南并使用了 def signup(),我应该只使用 def save()。我在网上找到了解决方案: