How do I make a custom User and Authentication system

I’ve created a custom User model and registration form but it just isn’t working; when I try registering a new user, no matter what I type in it throws an error saying the passwords don’t match. I can go into the admin area just fine and register users, but then in the database it stores their passwords unencrypted and it won’t let said users log in. I can register superusers just fine and log in without a problem with manage.py.

I am an absolute beginner at Django.

class RegisterForm(forms.ModelForm):
    """ Create a new user """
    password = forms.CharField(widget=forms.PasswordInput())
    confirm_password = forms.CharField(widget=forms.PasswordInput())

    class Meta:
        model = User
        fields = ('username', 'password')

    def clean_password(self):
        cleaned_data = super(RegisterForm, self).clean()
        password1 = cleaned_data.get('password')
        password2 = cleaned_data.get('confirm_password')

        #if password1 and password1 != password2:
            #raise forms.ValidationError("Passwords don't match.")
        return password2

    def save(self, commit=True):
        user = super(RegisterForm, self).save(commit=False)
        user.set_password(self.clean_password())
        if commit:
            user.save()
        return user

User and User Manager

class UserManager(BaseUserManager):
    user_in_migration = True

    def _create_user(self, username, password, **other):
        if not username:
            raise ValueError("The username must be set")
        user = self.model(username=username, **other)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, username, password=None, **other):
        other.setdefault('is_superuser', False)
        return self._create_user(username, password, **other)

    def create_superuser(self, username, password, **other):
        other.setdefault('is_superuser', True)

        if other.get('is_superuser') == False:
            raise ValueError('Superuser must have is_superuser=True')

        return self._create_user(username, password, **other)

class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(_('username'), max_length=64, null=True, unique=True, blank=False)
    is_superuser = models.BooleanField(_('is_superuser'), default=False)
    is_staff = models.BooleanField(default=True)

    joined = models.DateTimeField(_('joined'), auto_now_add=True)

    USERNAME_FIELD = 'username'
    objects = UserManager()

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

    def __str__(self):
        return self.username

Registration View:

class RegisterView(FormView):
    form_class = RegisterForm
    template_name = 'register.html'
    success_url = '/home'

    def form_valid(self, form):
        user = form.save(commit=False)
        user.save()
        login(self.request, user)
        if user is not None:
            return HttpResponseRedirect(self.success_url)

        return super().form_valid(form)

URL:

    path('register/', views.RegisterView.as_view(), name='register'),

In your RegisterForm, you don’t want to reference the model’s password field. You have two other fields, password1 and password2 which should be the fields in the form.

If you’re new with Django, you should take some time to look at how Django itself does this. See the UserCreationForm in django.contrib.auth.forms for an idea of how it’s done.

1 Like