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 Joe Michelini)

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:

  1. Start a new Django project and initiate an app.
  2. In models.py of your app, sub-class AbstractUser by importing it from django.contrib.auth.models.
  3. In settings.py, add AUTH_USER_MODEL=yourapp.YourSubClassedUser (this is all standard).
from django.contrib.auth.models import AbstractUser 

class User(AbstractUser): 
    pass 
  1. Register a view and associated url to render a UserCreationForm, perhaps using CreateView or FormView.
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
  1. Render the form in a template, and run migrations for the first time.
  2. 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.

Change History (1)

comment:1 by Joe Michelini, 4 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top