mirror of
https://github.com/django/django.git
synced 2025-07-19 09:09:13 +00:00
[1.9.x] 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. Backport of f0425c72601f466c6a71518749c6d15b94945514 from master
This commit is contained in:
parent
61f1b6ff21
commit
f78892f2de
@ -745,47 +745,45 @@ the "Model design considerations" note of :ref:`specifying-custom-user-model`.
|
|||||||
Custom users and the built-in auth forms
|
Custom users and the built-in auth forms
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
As you may expect, built-in Django's :ref:`forms <built-in-auth-forms>` and
|
Django's built-in :ref:`forms <built-in-auth-forms>` and :ref:`views
|
||||||
:ref:`views <built-in-auth-views>` make certain assumptions about the user
|
<built-in-auth-views>` make certain assumptions about the user model that they
|
||||||
model that they are working with.
|
are working with.
|
||||||
|
|
||||||
If your user model doesn't follow the same assumptions, it may be necessary to define
|
The following forms are compatible with any subclass of
|
||||||
a replacement form, and pass that form in as part of the configuration of the
|
:class:`~django.contrib.auth.models.AbstractBaseUser`:
|
||||||
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.
|
|
||||||
|
|
||||||
|
* :class:`~django.contrib.auth.forms.AuthenticationForm`: Uses the username
|
||||||
|
field specified by :attr:`~models.CustomUser.USERNAME_FIELD`.
|
||||||
* :class:`~django.contrib.auth.forms.SetPasswordForm`
|
* :class:`~django.contrib.auth.forms.SetPasswordForm`
|
||||||
|
|
||||||
Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
|
|
||||||
|
|
||||||
* :class:`~django.contrib.auth.forms.PasswordChangeForm`
|
* :class:`~django.contrib.auth.forms.PasswordChangeForm`
|
||||||
|
|
||||||
Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
|
|
||||||
|
|
||||||
* :class:`~django.contrib.auth.forms.AdminPasswordChangeForm`
|
* :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`
|
Custom users and :mod:`django.contrib.admin`
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
@ -10,6 +10,7 @@ from django.contrib.auth.forms import (
|
|||||||
SetPasswordForm, UserChangeForm, UserCreationForm,
|
SetPasswordForm, UserChangeForm, UserCreationForm,
|
||||||
)
|
)
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.auth.tests.custom_user import ExtensionUser
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.core.mail import EmailMultiAlternatives
|
from django.core.mail import EmailMultiAlternatives
|
||||||
@ -153,6 +154,21 @@ class UserCreationFormTest(TestDataMixin, TestCase):
|
|||||||
form['password2'].errors
|
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())
|
||||||
|
|
||||||
|
|
||||||
@override_settings(USE_TZ=False, PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'])
|
@override_settings(USE_TZ=False, PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'])
|
||||||
class AuthenticationFormTest(TestDataMixin, TestCase):
|
class AuthenticationFormTest(TestDataMixin, TestCase):
|
||||||
@ -441,6 +457,24 @@ class UserChangeFormTest(TestDataMixin, TestCase):
|
|||||||
# value to render correctly
|
# value to render correctly
|
||||||
self.assertEqual(form.initial['password'], form['password'].value())
|
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(
|
@override_settings(
|
||||||
PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'],
|
PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user