Opened 4 years ago
Last modified 4 years ago
#32599 closed Uncategorized
django.contrib.auth.forms.py should always refer to User as get_user_model() — at Version 1
Reported by: | Joe Michelini | Owned by: | Joe Michelini |
---|---|---|---|
Component: | contrib.auth | Version: | 3.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Inconsistent Reference
In some sections of django.contrib.auth.forms.py
, when referring to the User model, Django wisely uses get_user_model()
, so whether we decide to use the built-in User model, extend it, or use our own, we always get the right user when importing these forms.
However, in the UserCreationForm
for example, Django instead explicitly refers to the built-in user found at django.contrib.auth.models
.
This causes some forms to work and some forms to fail when using a custom or extended User model, even though extending the built-in User model is suggested in the Django documentation.
This is an easy fix and would require all forms in django.contrib.auth.forms
to refer to get_user_model()
as opposed to the imported built-in User
. In the case where a custom User model is not being utilized, get_user_model()
will automatically refer to the built-in User.
To reproduce:
- Start a new Django project and initiate an app.
- In
models.py
of your app, sub-classAbstractUser
by importing it fromdjango.contrib.auth.models
. - In settings.py, add
AUTH_USER_MODEL=yourapp.YourSubClassedUser
(this is all standard).
from django.contrib.auth.models import AbstractUser class User(AbstractUser): pass
- Register a view and associated url to render a
UserCreationForm
, perhaps usingCreateView
orFormView
.
from django.shortcuts import render from .models import User from django.contrib.auth.forms import UserCreationForm from django.views.generic.edit import FormView, CreateView class RegisterView(CreateView): model = User form_class = UserCreationForm template_name = 'users/register.html
- Render the form in a template, and run migrations for the first time.
- Attempt to start the server. This will throw the following error:
AttributeError: Manager isn't available; 'auth.User' has been swapped for 'users.User'
In the documentation, Django claims that sub-classing the built-in User is not only recommended, but that it will behave exactly like the built-in User model. Patching django.contrib.auth.forms.py
would ensure this.