1

I have my own user model called 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.

Ty C
  • 69
  • 9
  • could it be that field named "username" is not defined in your model? Then empty value is set for the field and you hit unique constraint. – Capacytron Nov 14 '18 at 01:49
  • @sergey thanks for the response. Do you think you could provide an example or elaborate on this? – Ty C Nov 14 '18 at 05:58

1 Answers1

1

Rather than subclassing from AbstractUser, I think its better to subclass from 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. 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. 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.

Or you can still use AbstractUser but need to override the username field

class User(AbstractBaseUser, PermissionsMixin):
     username = models.CharField(_('username'), max_length=255, blank=True, unique=False)
...
# rest of your fields
ruddra
  • 50,746
  • 7
  • 78
  • 101