Django create custom UserCreationForm
Asked Answered
C

3

26

I enabled the user auth module in Django, however when I use UserCreationForm it only asks for username and the two password/password confirmation fields. I also want email and fullname fields, all set as required fields.

I've done this:

from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User

class RegisterForm(UserCreationForm):
    email = forms.EmailField(label = "Email")
    fullname = forms.CharField(label = "Full name")

    class Meta:
        model = User
        fields = ("username", "fullname", "email", )

Now the form shows the new fields but it doesn't save them to the database.

How can I fix this?

Caxton answered 21/4, 2011 at 14:5 Comment(0)
U
28

There is no such field called fullname in the User model.

If you wish to store the name using the original model then you have to store it separately as a first name and last name.

Edit: If you want just one field in the form and still use the original User model use the following:

You can do something like this:

from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User

class RegisterForm(UserCreationForm):
    email = forms.EmailField(label = "Email")
    fullname = forms.CharField(label = "First name")

    class Meta:
        model = User
        fields = ("username", "fullname", "email", )

Now you have to do what manji has said and override the save method, however since the User model does not have a fullname field it should look like this:

def save(self, commit=True):
        user = super(RegisterForm, self).save(commit=False)
        first_name, last_name = self.cleaned_data["fullname"].split()
        user.first_name = first_name
        user.last_name = last_name
        user.email = self.cleaned_data["email"]
        if commit:
            user.save()
        return user

Note: You should add a clean method for the fullname field that will ensure that the fullname entered contains only two parts, the first name and last name, and that it has otherwise valid characters.

Reference Source Code for the User Model:

http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py#L201
Unlookedfor answered 21/4, 2011 at 14:29 Comment(8)
Good answer dude. I don't care for a 'full_name' field in the database, but can I edit the registration form to ask not the first name and the last name but one field 'full name'?Caxton
I'm not quite sure I follow... You're saying you want to have just one field in the form for the fullname but you don't care if it gets saved or not? Or are you asking how to have one fullname field and still be able to save it using the User model?Unlookedfor
I want one field called "Full name" in the form, but I want to save it in a fullname field on the User model. If I can't, split the fullname field for save in the first_name and in the last_name fields on the model.Caxton
How do you get this to actually replace the standard UserCreationForm? I created a custom user admin and set the add_form = CustomUserCreationForm, but it does not display when I go to add a user in the admin page.Antinode
You would also have to replace the standard template for that page I think. This is a great resource on the topic and you can probably find your answer in there. Unfortunately I can't help too much right now since I'm at work but I'll see if I have time to do something at home.Unlookedfor
Has anyone had any IntegrityErrors using this? Somehow on the if comit: user.save() I get IntegrityError: (1062, “Duplicate entry ‘MyUsername’ for key 'username'”) Even thought I have a clean_username function to protect against that.Fogbound
Be careful with the following line of code: first_name, last_name = self.cleaned_data["fullname"].split() This raises 'ValueError: too many values to unpack' if fullname is something like "Foo Bar Baz" (e.g. two instances of whitespace if your user has a middle name). I use a slight variation which stuffs everything after the initial whitespace into the last_name: first_name, last_name = self.cleaned_data["fullname"].split(None, 1)Jerlenejermain
For the class Meta, do you need passwords fields to also be included? For example: fields = ("username", "fullname", "email", "password1", "password2")? The above does not include password1/password2 so I wanted to confirm.Resurrect
S
7

You have to override UserCreationForm.save() method:

    def save(self, commit=True):
        user = super(RegisterForm, self).save(commit=False)
        user.fullname = self.cleaned_data["fullname"]
        user.email = self.cleaned_data["email"]
        if commit:
            user.save()
        return user

http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/forms.py#L10

Sensualism answered 21/4, 2011 at 14:19 Comment(0)
R
4

In django 1.10 this is what I wrote in admin.py to add first_name, email and last_name to the default django user creation form

from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib import admin
from django.contrib.auth.models import Group, User

# first unregister the existing useradmin...
admin.site.unregister(User)

class UserAdmin(BaseUserAdmin):
    # The forms to add and change user instances
    # The fields to be used in displaying the User model.
    # These override the definitions on the base UserAdmin
    # that reference specific fields on auth.User.
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
    fieldsets = (
    (None, {'fields': ('username', 'password')}),
    ('Personal info', {'fields': ('first_name', 'last_name', 'email',)}),
    ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
    ('Important dates', {'fields': ('last_login', 'date_joined')}),)
    # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
    # overrides get_fieldsets to use this attribute when creating a user.
    add_fieldsets = (
    (None, {
        'classes': ('wide',),
        'fields': ('username', 'email', 'first_name', 'last_name', 'password1', 'password2')}),)
    list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
    search_fields = ('username', 'first_name', 'last_name', 'email')
    ordering = ('username',)
    filter_horizontal = ('groups', 'user_permissions',)

# Now register the new UserAdmin...
admin.site.register(User, UserAdmin)
Reiterant answered 23/9, 2016 at 12:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.