Opened 5 years ago

Last modified 7 days ago

#28608 assigned Cleanup/optimization

Allow UserCreationForm and UserChangeForm to work with custom user models

Reported by: Rômulo Collopy Owned by: Aman Pandey
Component: contrib.auth Version: dev
Severity: Normal Keywords: user, custom user, auth
Cc: Lemuel Formacil Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


class UserChangeForm(forms.ModelForm):
    # ...
    class Meta:
        model = User


class UserCreationForm(forms.ModelForm):
    class Meta:
        model = User

could use UserModel instead of User. It is already defined in and is used in other forms of the same package.

This would allow Django Registration and other packages that use these forms to work out of the box. And it would allow using them with no need to rewitte as specified at

Attachments (1)

patch.diff (2.2 KB) - added by Rômulo Collopy 5 years ago.

Download all attachments as: .zip

Change History (9)

Changed 5 years ago by Rômulo Collopy

Attachment: patch.diff added


comment:1 Changed 5 years ago by Tim Graham

Patch needs improvement: set
Summary: UserCreationForm and UserChangeForm model using get_user_modelAllow UserCreationForm and UserChangeForm to work with custom user models

This is a continuation of #19353.

comment:2 Changed 5 years ago by Tim Graham

Triage Stage: UnreviewedAccepted

comment:3 Changed 5 years ago by shangdahao

Owner: changed from nobody to shangdahao
Patch needs improvement: unset
Status: newassigned

Since This ticket is related to ticket 28757, I made the changes for this ticket and ticket 28757 in the same commit.


comment:4 Changed 5 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

In 3333d93:

Fixed #28757 -- Allowed using contrib.auth forms without installing contrib.auth.

Also fixed #28608 -- Allowed UserCreationForm and UserChangeForm to
work with custom user models.

Thanks Sagar Chalise and Rômulo Collopy for reports, and Tim Graham
and Tim Martin for reviews.

comment:5 Changed 4 years ago by Tim Graham

Has patch: unset
Resolution: fixed
Status: closednew

In f3fa86a89b3b85242f49b2b9acf58b5ea35acc1f:

Fixed #29449 -- Reverted "Fixed #28757 -- Allowed using contrib.auth forms without installing contrib.auth."

This reverts commit 3333d935d2914cd80cf31f4803821ad5c0e2a51d due to a crash if USERNAME_FIELD isn't a CharField.

comment:6 Changed 4 years ago by Lemuel Formacil

Another non-standard behavior of the UserCreationForm when used with a custom user model is if the model has a ManyToManyField the form will not save the value of the ManyToManyField. From the documentation:

If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.

To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.

However, the method initially calls the form's save method with commit=False but then doesn't call the save_m2m method after committing the instance if commit=True. The save() method should be something like this so the form would behave as expected with custom user models with a many-to-many relation:

def save(self, commit=True):
    user = super().save(commit=False)
    if commit:
        self.save_m2m()  # added this call to work as expected with models with `ManyToManyField`s
    return user
Last edited 4 years ago by Lemuel Formacil (previous) (diff)

comment:7 Changed 4 years ago by Lemuel Formacil

Cc: Lemuel Formacil added

comment:8 Changed 7 days ago by Aman Pandey

Owner: changed from shangdahao to Aman Pandey
Status: newassigned
Note: See TracTickets for help on using tickets.
Back to Top