Create User ModelForm and working with it

Hi everyone !

I’m currently trying to understand how a User ModelForm can work by writing both the model and the form myself.

Here is my code :

models.py

from django.db import models

class UserModel(models.Model):
    username = models.CharField(max_length=20)
    email = models.CharField(max_length=20)
    password1 = models.CharField(max_length=20)
    password2 = models.CharField(max_length=20)

forms.py

from django.forms import ModelForm
from django.forms.widgets import PasswordInput
from .models import UserModel

class UserModelForm(ModelForm):
    class Meta:
        model = UserModel
        fields = [
            "username",
            "email",
            "password1",
            "password2",
            ]

        widgets = {
            "password1":PasswordInput(),
            "password2":PasswordInput(),
        }

views.py

from django.shortcuts import render
from .forms import UserModelForm

def signupUser(request):
    if request.method == "POST":
        form = UserModelForm(request.POST)

        if form.is_valid():
            form.save()
        else:
            print(form.errors)
    else:
        form = UserModelForm()

    template_name = "accounts/signup.html"
    context = {
        "form":form,
    }

    return render(request, template_name, context)

signup.html

{% extends "base.html" %}

{% block page_title %}{% endblock %}

{% block page_content %}
<form id="signupForm" action="accounts:signupUser" method="POST">
    {% csrf_token %}

    {{ form.username.label }}
    {{ form.username }}

    {{ form.email.label }}
    {{ form.email }}
    
    {{ form.password1.label }}
    {{ form.password1 }}

    {{ form.password2.label }}
    {{ form.password2 }}

    <input value ="Sign Up" type="submit">
</form>
{% endblock %}

What I want to achieve is basically validating the form after the “Sign Up” button has been pressed and then save it in my DB.

As I intend to create my own model and form, I have to explicitely code it, do you have a clue on how I could do it my self ? (Checking passwords, cleaning fields, saving)

Best Regards

I’m not sure why you need to create your own form since UserCreationForm exists, but, if you must create the form yourself, then I think you’d need roughly:

  • A clean_username method to ensure the username is not already associated with another user
  • A clean_email method for a similar purpose (and I might suggest that you use EmailField on your model to save you a lot of extra validation work).
  • A clean method that can compare the two passwords and make sure they match. It would also need to call validate_password to run the password through all the validators and make sure it’s not too weak.
  • A save method that creates a User object. As you’ve written your UserModel at the moment, you’d be storing the password in plain text. That’s not good. I’d suggest you consider reading https://docs.djangoproject.com/en/3.1/topics/auth/customizing/#specifying-custom-user-model to learn how to create a custom user model that does password management correctly. That would give you access to user.set_password so that you can store your password as a hash. Any of your future users will thank you. :smile:

I hope that helps a bit.

1 Like

Hi @mblayman ! Thanks for your answer.

I understand better now. So I will use the AbstractBaseUser as a basis to understand the whole process.

I found this page where I can see every User methods implemented : https://github.com/django/django/blob/master/django/contrib/auth/base_user.py

That’s why I’ve changed my models.py :

from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser

class UserModel(AbstractBaseUser):
    username = models.CharField(max_length=20, unique=True)
    email = models.EmailField(max_length=40)
    password1 = models.CharField(max_length=20)
    password2 = models.CharField(max_length=20)

Yet I now have a new issue, my signup.html page doesn’t render fields anymore, do you have an idea why ? Because I still use the same forms.py file

EDIT :

After reviewing my code, the fields were not rendered because I rewrote my views.py file without adding a form to the context, it’s okay now :wink: