简体   繁体   English

Django自定义身份验证模型注册表返回唯一用户名错误

[英]Django custom auth model registration form returns unique username error

I have my own user model called User.我有自己的用户模型,称为 User。 I have a user registration form that returns this error below:我有一个用户注册表,在下面返回此错误:

duplicate key value violates unique constraint "users_user_username_06e46fe6_uniq"
DETAIL:  Key (username)=() already exists.

Could it be that the user model is getting saved twice?可能是用户模型被保存了两次?

This is my form:这是我的表格:

class FighterSignUpForm(UserCreationForm):
        class Meta(UserCreationForm.Meta):
            model = User
            fields = ('first_name', 'last_name','email','password1', 'password2',)

        @transaction.atomic
        def save(self):
            user = super().save(commit=False)
            user.is_fighter = True
            user.is_active = False
            user.save()
        return user

This is my view:这是我的观点:

class FighterSignUpView(CreateView):

    model = User
    form_class = FighterSignUpForm
    template_name = 'registration/user_signup.html'

    def get_context_data(self, **kwargs):
        kwargs['user_type'] = 'example'
        return super().get_context_data(**kwargs)

    def form_valid(self, form):
        user = form.save()

This is the custom user model:这是自定义用户模型:

        class UserManager(BaseUserManager):

            use_in_migrations = True

            def _create_user(self, email, password, **extra_fields):
                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):
                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):
                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)

        class User(AbstractUser):
            email = models.EmailField(_('Email'), unique=True)

            USERNAME_FIELD = 'email'
            REQUIRED_FIELDS = []

            is_type1 = models.BooleanField(default=False, verbose_name="type1")
            is_type2 = models.BooleanField(default=False, verbose_name="type2")
            is_type3 = models.BooleanField(default=False, verbose_name="type")
            is_confirmed = models.BooleanField(default=False, verbose_name="Has Confirmed Email")

            objects = UserManager()

I have just recently moved my database from SQlite3 and have not had this problem whatsoever when running the former.我最近刚刚从 SQlite3 移动了我的数据库,并且在运行前者时没有遇到过这个问题。

Rather than subclassing from AbstractUser , I think its better to subclass from AbstractBaseUser .与其从AbstractUser子类AbstractUser ,我认为从AbstractBaseUser子类化更好。 Because AbstractUser has username field and its unique by default, but AbstractBaseUser only has password and last_login field, and it provides core implementation of User model.因为AbstractUser默认有username字段并且是唯一的,而AbstractBaseUser只有passwordlast_login字段,它提供了 User 模型的核心实现。 There is a down side as well, like, AbstarctBaseUser does not have is_staff , first_name , last_name , is_superuser fields and permission related fields are missing as well.有不好的一面,以及像, AbstarctBaseUser没有is_stafffirst_namelast_nameis_superuser领域和权限相关领域的缺失,以及。 So, better if you use it like this:所以,如果你像这样使用它会更好:

class User(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField(_('first name'), max_length=255, blank=True)
    last_name = models.CharField(_('last name'), max_length=255, blank=True)
    email = models.EmailField(_('email address'), blank=True, max_length=50)
    is_staff = models.BooleanField(_('staff status'), default=False,
                                help_text=_('Designates whether the user'
                                            ' can log into this admin '
                                            'site.'))
    is_active = models.BooleanField(_('active'), default=True,
                                    help_text=_('Designates whether '
                                                'this user should be '
                                                ' treated as '
                                                'active. Unselect this '
                                                ' instead of '
                                                ' deleting accounts.'))
    objects = UserManager()
    # rest of your fields

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['email']

    def get_short_name(self):
        return self.first_name

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

Please check here about using custom user model for more details.在此处查看有关使用自定义用户模型的更多详细信息。 Also you can check this SO answer about differences between AbstractBaseUser and AbstractUser .您也可以检查这个SO answer关于AbstractBaseUserAbstractUser之间的差异。

Or you can still use AbstractUser but need to override the username field或者你仍然可以使用AbstractUser但需要覆盖username

class User(AbstractBaseUser, PermissionsMixin):
     username = models.CharField(_('username'), max_length=255, blank=True, unique=False)
...
# rest of your fields

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM