diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py
index 9279c52..0c542be 100644
a
|
b
|
class UserCreationForm(forms.ModelForm):
|
82 | 82 | def clean_username(self): |
83 | 83 | # Since User.username is unique, this check is redundant, |
84 | 84 | # but it sets a nicer error message than the ORM. See #13147. |
| 85 | UserModel = self._meta.model |
85 | 86 | username = self.cleaned_data["username"] |
86 | 87 | try: |
87 | | User.objects.get(username=username) |
88 | | except User.DoesNotExist: |
| 88 | UserModel.objects.get(username=username) |
| 89 | except UserModel.DoesNotExist: |
89 | 90 | return username |
90 | 91 | raise forms.ValidationError(self.error_messages['duplicate_username']) |
91 | 92 | |
diff --git a/django/contrib/auth/tests/forms.py b/django/contrib/auth/tests/forms.py
index f3eb242..b63624c 100644
a
|
b
|
from django.contrib.auth.models import User
|
5 | 5 | from django.contrib.auth.forms import (UserCreationForm, AuthenticationForm, |
6 | 6 | PasswordChangeForm, SetPasswordForm, UserChangeForm, PasswordResetForm) |
7 | 7 | from django.contrib.auth.tests.utils import skipIfCustomUser |
| 8 | from django.contrib.auth.tests.custom_user import ExtensionUser |
8 | 9 | from django.core import mail |
9 | 10 | from django.forms.fields import Field, EmailField |
10 | 11 | from django.test import TestCase |
… |
… |
class PasswordResetFormTest(TestCase):
|
362 | 363 | self.assertFalse(form.is_valid()) |
363 | 364 | self.assertEqual(form["email"].errors, |
364 | 365 | [_("The user account associated with this email address cannot reset the password.")]) |
| 366 | |
| 367 | |
| 368 | @override_settings(AUTH_USER_MODEL='auth.ExtensionUser') |
| 369 | class CustomUserCreationFormTest(TestCase): |
| 370 | def test_form_validates(self): |
| 371 | class CustomUserCreationForm(UserCreationForm): |
| 372 | class Meta(UserCreationForm.Meta): |
| 373 | model = ExtensionUser |
| 374 | data = { |
| 375 | 'username': 'jsmith', |
| 376 | 'password1': 'test123', |
| 377 | 'password2': 'test123', |
| 378 | } |
| 379 | form = CustomUserCreationForm(data) |
| 380 | self.assertTrue(form.is_valid()) |
diff --git a/docs/topics/auth.txt b/docs/topics/auth.txt
index e313b23..297214c 100644
a
|
b
|
As you may expect, built-in Django's :ref:`forms <built-in-auth-forms>`
|
2061 | 2061 | and :ref:`views <other-built-in-views>` make certain assumptions about |
2062 | 2062 | the user model that they are working with. |
2063 | 2063 | |
2064 | | If your user model doesn't follow the same assumptions, it may be necessary to define |
2065 | | a replacement form, and pass that form in as part of the configuration of the |
2066 | | auth views. |
| 2064 | The following forms are compatible with any subclass of |
| 2065 | :class:`~django.contrib.auth.models.AbstractBaseUser`: |
2067 | 2066 | |
2068 | | * :class:`~django.contrib.auth.forms.UserCreationForm` |
| 2067 | * :class:`~django.contrib.auth.forms.AuthenticationForm` |
2069 | 2068 | |
2070 | | Depends on the :class:`~django.contrib.auth.models.User` model. |
2071 | | Must be re-written for any custom user model. |
| 2069 | Uses the field defined in `USERNAME_FIELD`. |
2072 | 2070 | |
2073 | | * :class:`~django.contrib.auth.forms.UserChangeForm` |
| 2071 | * :class:`~django.contrib.auth.forms.SetPasswordForm` |
2074 | 2072 | |
2075 | | Depends on the :class:`~django.contrib.auth.models.User` model. |
2076 | | Must be re-written for any custom user model. |
| 2073 | * :class:`~django.contrib.auth.forms.PasswordChangeForm` |
2077 | 2074 | |
2078 | | * :class:`~django.contrib.auth.forms.AuthenticationForm` |
| 2075 | * :class:`~django.contrib.auth.forms.AdminPasswordChangeForm` |
2079 | 2076 | |
2080 | | Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser`, |
2081 | | and will adapt to use the field defined in `USERNAME_FIELD`. |
| 2077 | The following forms make assumptions about the user model and can be used as-is if they are met: |
2082 | 2078 | |
2083 | 2079 | * :class:`~django.contrib.auth.forms.PasswordResetForm` |
2084 | 2080 | |
… |
… |
auth views.
|
2086 | 2082 | `email` that can be used to identify the user, and a boolean field |
2087 | 2083 | named `is_active` to prevent password resets for inactive users. |
2088 | 2084 | |
2089 | | * :class:`~django.contrib.auth.forms.SetPasswordForm` |
| 2085 | Finally, the following forms are tied directly to auth.User and need to be re-written or extended to work with a custom user model: |
2090 | 2086 | |
2091 | | Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser` |
| 2087 | * :class:`~django.contrib.auth.forms.UserCreationForm` |
2092 | 2088 | |
2093 | | * :class:`~django.contrib.auth.forms.PasswordChangeForm` |
| 2089 | * :class:`~django.contrib.auth.forms.UserChangeForm` |
2094 | 2090 | |
2095 | | Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser` |
2096 | 2091 | |
2097 | | * :class:`~django.contrib.auth.forms.AdminPasswordChangeForm` |
| 2092 | If your custom user model is a simple subclass of |
| 2093 | :class:`~django.contrib.auth.models.AbstractUser`, then you can extend the forms |
| 2094 | in this manner:: |
| 2095 | |
| 2096 | from django.contrib.auth.forms import UserCreationForm |
| 2097 | from myapp.models import CustomUser |
2098 | 2098 | |
2099 | | Works with any subclass of :class:`~django.contrib.auth.models.AbstractBaseUser` |
| 2099 | class CustomUserCreationForm(UserCreationForm): |
| 2100 | class Meta(UserCreationForm.Meta): |
| 2101 | model = CustomUser |
2100 | 2102 | |
2101 | 2103 | |
2102 | 2104 | Custom users and django.contrib.admin |