Refs #19353 -- Added tests for using custom user models with built-in auth forms.
Also updated topics/auth/customizing.txt to reflect that subclasses of UserCreationForm and UserChangeForm can be used with custom user models. Thanks Baptiste Mispelon for the initial documentation.
This commit is contained in:
parent
d4dc775620
commit
f0425c7260
|
@ -733,47 +733,45 @@ the "Model design considerations" note of :ref:`specifying-custom-user-model`.
|
|||
Custom users and the built-in auth forms
|
||||
----------------------------------------
|
||||
|
||||
As you may expect, built-in Django's :ref:`forms <built-in-auth-forms>` and
|
||||
:ref:`views <built-in-auth-views>` make certain assumptions about the user
|
||||
model that they are working with.
|
||||
Django's built-in :ref:`forms <built-in-auth-forms>` and :ref:`views
|
||||
<built-in-auth-views>` make certain assumptions about the user model that they
|
||||
are working with.
|
||||
|
||||
If your user model doesn't follow the same assumptions, it may be necessary to define
|
||||
a replacement form, and pass that form in as part of the configuration of the
|
||||
auth views.
|
||||
|
||||
* :class:`~django.contrib.auth.forms.UserCreationForm`
|
||||
|
||||
Depends on the :class:`~django.contrib.auth.models.User` model.
|
||||
Must be re-written for any custom user model.
|
||||
|
||||
* :class:`~django.contrib.auth.forms.UserChangeForm`
|
||||
|
||||
Depends on the :class:`~django.contrib.auth.models.User` model.
|
||||
Must be re-written for any custom user model.
|
||||
|
||||
* :class:`~django.contrib.auth.forms.AuthenticationForm`
|
||||
|
||||
Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`,
|
||||
and will adapt to use the field defined in ``USERNAME_FIELD``.
|
||||
|
||||
* :class:`~django.contrib.auth.forms.PasswordResetForm`
|
||||
|
||||
Assumes that the user model has a field named ``email`` that can be used to
|
||||
identify the user and a boolean field named ``is_active`` to prevent
|
||||
password resets for inactive users.
|
||||
The following forms are compatible with any subclass of
|
||||
:class:`~django.contrib.auth.models.AbstractBaseUser`:
|
||||
|
||||
* :class:`~django.contrib.auth.forms.AuthenticationForm`: Uses the username
|
||||
field specified by :attr:`~models.CustomUser.USERNAME_FIELD`.
|
||||
* :class:`~django.contrib.auth.forms.SetPasswordForm`
|
||||
|
||||
Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
|
||||
|
||||
* :class:`~django.contrib.auth.forms.PasswordChangeForm`
|
||||
|
||||
Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
|
||||
|
||||
* :class:`~django.contrib.auth.forms.AdminPasswordChangeForm`
|
||||
|
||||
Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
|
||||
The following forms make assumptions about the user model and can be used as-is
|
||||
if those assumptions are met:
|
||||
|
||||
* :class:`~django.contrib.auth.forms.PasswordResetForm`: Assumes that the user
|
||||
model has a field named ``email`` that can be used to identify the user and a
|
||||
boolean field named ``is_active`` to prevent password resets for inactive
|
||||
users.
|
||||
|
||||
Finally, the following forms are tied to
|
||||
:class:`~django.contrib.auth.models.User` and need to be rewritten or extended
|
||||
to work with a custom user model:
|
||||
|
||||
* :class:`~django.contrib.auth.forms.UserCreationForm`
|
||||
* :class:`~django.contrib.auth.forms.UserChangeForm`
|
||||
|
||||
If your custom user model is a simple subclass of ``AbstractUser``, then you
|
||||
can extend these forms in this manner::
|
||||
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from myapp.models import CustomUser
|
||||
|
||||
class CustomUserCreationForm(UserCreationForm):
|
||||
|
||||
class Meta(UserCreationForm.Meta):
|
||||
model = CustomUser
|
||||
fields = UserCreationForm.Meta.fields + ('custom_field',)
|
||||
|
||||
Custom users and :mod:`django.contrib.admin`
|
||||
--------------------------------------------
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from django import forms
|
||||
|
@ -19,6 +20,7 @@ from django.utils.encoding import force_text
|
|||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from .models.custom_user import ExtensionUser
|
||||
from .settings import AUTH_TEMPLATES
|
||||
|
||||
|
||||
|
@ -122,6 +124,21 @@ class UserCreationFormTest(TestDataMixin, TestCase):
|
|||
form['password2'].errors
|
||||
)
|
||||
|
||||
def test_custom_form(self):
|
||||
class CustomUserCreationForm(UserCreationForm):
|
||||
class Meta(UserCreationForm.Meta):
|
||||
model = ExtensionUser
|
||||
fields = UserCreationForm.Meta.fields + ('date_of_birth',)
|
||||
|
||||
data = {
|
||||
'username': 'testclient',
|
||||
'password1': 'testclient',
|
||||
'password2': 'testclient',
|
||||
'date_of_birth': '1988-02-24',
|
||||
}
|
||||
form = CustomUserCreationForm(data)
|
||||
self.assertTrue(form.is_valid())
|
||||
|
||||
|
||||
class AuthenticationFormTest(TestDataMixin, TestCase):
|
||||
|
||||
|
@ -407,6 +424,24 @@ class UserChangeFormTest(TestDataMixin, TestCase):
|
|||
# value to render correctly
|
||||
self.assertEqual(form.initial['password'], form['password'].value())
|
||||
|
||||
def test_custom_form(self):
|
||||
class CustomUserChangeForm(UserChangeForm):
|
||||
class Meta(UserChangeForm.Meta):
|
||||
model = ExtensionUser
|
||||
fields = ('username', 'password', 'date_of_birth',)
|
||||
|
||||
user = User.objects.get(username='testclient')
|
||||
data = {
|
||||
'username': 'testclient',
|
||||
'password': 'testclient',
|
||||
'date_of_birth': '1998-02-24',
|
||||
}
|
||||
form = CustomUserChangeForm(data, instance=user)
|
||||
self.assertTrue(form.is_valid())
|
||||
form.save()
|
||||
self.assertEqual(form.cleaned_data['username'], 'testclient')
|
||||
self.assertEqual(form.cleaned_data['date_of_birth'], datetime.date(1998, 2, 24))
|
||||
|
||||
|
||||
@override_settings(TEMPLATES=AUTH_TEMPLATES)
|
||||
class PasswordResetFormTest(TestDataMixin, TestCase):
|
||||
|
|
Loading…
Reference in New Issue