UserCreationForm with 11 fields

Something simple is amiss here.

I am trying to allow someone to register for a site, and am trying to use the standard UserCreationForm. What happens is a form with 11 fields, not the three mentioned in the documentation.

Here is the form that shows up has these fields in order:
Password
Last Login
Superuser status
Groups
User permissions
Username
First name
Last name
Email address

I believe the problem must be in the view. Here it is:

from django.urls import reverse_lazy
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth.forms import UserCreationForm

class Signup(SuccessMessageMixin, generic.CreateView):
    form = UserCreationForm
    fields = '__all__'
    model = User
    template_name = 'signup.html'
    success_url = reverse_lazy('glazes:home page')

The template signup.html is just this:

{% extends "base.html" %}

{% block title %}
Site sign up
{% endblock %}
{% block content %}
<h3>Sign up</h3>
<hr>
<form method = "post">
{% csrf_token %}
{{ form.as_p }}
<br>
<input type="submit" value="Save">
</form>
{% endblock %}

The urls.py contains the following line. I only include it here for completeness:

    path('accounts/signup', views.Signup.as_view(), name='sign up'),

I really expected a form with just the three fields: username and password1 and password2.
It seemed like using the generic.CreateView and UserCreationForm was the thing to do, but apparently not. Any suggestion how to do this correctly with a class view?

Review the fields directive in the documentation.

You’re saying with this line that you want all the fields in the model on the form.

I get that. But the documentation says there are only supposed to be three fields. And I don’t get one of those. Do you think the generic.CreateView is the right one to use?

I just changed the line in the view to:

fields =  ['username', 'password1', 'password2']

and got this error when accessing the page:

Unknown field(s) (password2, password1) specified for User

Regarding your earlier response, what documentation are you referring to?

(Oh, and CreateView is probably as good as anything else for doing this.)

Regarding the second response, that’s because your model doesn’t have fields named password1 and password2. They’re defined in the form itself as form fields and not model fields. That means they don’t get defined in the fields list - they’re defined in the form.

You need to add a validation function for your view to validate password1 and password2, and then properly encrypt the password (from either field - they should be the same) and insert that into the password field. (You can look at the source for django.contrib.auth.admin.UserAdmin to see how they handle that form. That should give you some ideas.)

Ken

Thank you Ken.

The documentation I was referring to was from:


where it says:
class UserCreationForm¶
A ModelForm for creating a new user.

It has three fields: username (from the user model), password1, and password2. It verifies that password1 and password2 match, validates the password using validate_password(), and sets the user’s password using set_password().

I will read up on the distinction between form fields and model fields. I am obviously confused on this.

I just found the key to this solution.
The class Signup View originally had:

form = UserCreationForm

changing that to:

form_class = UserCreationForm

fixed it.

Cool! Glad to see you’ve got it working.

Regarding the field types, try not to over-think it (it’s easy enough to do in this case). The distinction is important, but isn’t that complex.

The Form fields are the fields (widgets) that appear in the browser. The Model fields are those fields existing in the database.

The two don’t need to exactly correspond with each other. You can have fields in your database that don’t appear on forms, and you can have fields that show up on a page that don’t get saved to the database. Each are defined in their respective classes.

Where some confusion may occur is that a ModelForm will automatically create Form fields for you - and the fields it creates are created from the fields list. It’s not that it’s using the same fields - the fields are still distinct - it’s just that Django is creating them for you from some defaults instead of you having to create them yourself.

Cheers!
Ken

1 Like

Thank you for the explanation. You are always instructive and much appreciated.