summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBerker Peksag <berker.peksag@gmail.com>2016-02-14 17:30:01 +0200
committerTim Graham <timograham@gmail.com>2016-02-17 10:42:54 -0500
commitf78892f2de1e986f00d23581dc006e90e26abd8f (patch)
treea5db18a810724cdd93bfe3e2f2a7bf2fc29239ce
parent61f1b6ff219a72902c81135ad4fb1db190f103f6 (diff)
[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
-rw-r--r--docs/topics/auth/customizing.txt60
-rw-r--r--tests/auth_tests/test_forms.py34
2 files changed, 63 insertions, 31 deletions
diff --git a/docs/topics/auth/customizing.txt b/docs/topics/auth/customizing.txt
index 0310658cf0..48eb4bb019 100644
--- a/docs/topics/auth/customizing.txt
+++ b/docs/topics/auth/customizing.txt
@@ -745,47 +745,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``.
+The following forms are compatible with any subclass of
+:class:`~django.contrib.auth.models.AbstractBaseUser`:
-* :class:`~django.contrib.auth.forms.PasswordResetForm`
+* :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.PasswordChangeForm`
+* :class:`~django.contrib.auth.forms.AdminPasswordChangeForm`
- 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 make assumptions about the user model and can be used as-is
+if those assumptions are met:
-* :class:`~django.contrib.auth.forms.SetPasswordForm`
+* :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.
- Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
+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.PasswordChangeForm`
+* :class:`~django.contrib.auth.forms.UserCreationForm`
+* :class:`~django.contrib.auth.forms.UserChangeForm`
- Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
+If your custom user model is a simple subclass of ``AbstractUser``, then you
+can extend these forms in this manner::
-* :class:`~django.contrib.auth.forms.AdminPasswordChangeForm`
+ from django.contrib.auth.forms import UserCreationForm
+ from myapp.models import CustomUser
- Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`
+ class CustomUserCreationForm(UserCreationForm):
+ class Meta(UserCreationForm.Meta):
+ model = CustomUser
+ fields = UserCreationForm.Meta.fields + ('custom_field',)
Custom users and :mod:`django.contrib.admin`
--------------------------------------------
diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py
index 79f0f65628..918fe3801a 100644
--- a/tests/auth_tests/test_forms.py
+++ b/tests/auth_tests/test_forms.py
@@ -10,6 +10,7 @@ from django.contrib.auth.forms import (
SetPasswordForm, UserChangeForm, UserCreationForm,
)
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.core import mail
from django.core.mail import EmailMultiAlternatives
@@ -153,6 +154,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())
+
@override_settings(USE_TZ=False, PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'])
class AuthenticationFormTest(TestDataMixin, TestCase):
@@ -441,6 +457,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(
PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'],