mirror of
				https://github.com/django/django.git
				synced 2025-11-04 13:39:16 +00:00 
			
		
		
		
	Fixed #29449 -- Reverted "Fixed #28757 -- Allowed using contrib.auth forms without installing contrib.auth."
This reverts commit 3333d935d2 due to
a crash if USERNAME_FIELD isn't a CharField.
			
			
This commit is contained in:
		
							parent
							
								
									eac9ab7ebb
								
							
						
					
					
						commit
						f3fa86a89b
					
				
					 4 changed files with 60 additions and 132 deletions
				
			
		| 
						 | 
					@ -7,6 +7,7 @@ from django.contrib.auth import (
 | 
				
			||||||
from django.contrib.auth.hashers import (
 | 
					from django.contrib.auth.hashers import (
 | 
				
			||||||
    UNUSABLE_PASSWORD_PREFIX, identify_hasher,
 | 
					    UNUSABLE_PASSWORD_PREFIX, identify_hasher,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
from django.contrib.auth.tokens import default_token_generator
 | 
					from django.contrib.auth.tokens import default_token_generator
 | 
				
			||||||
from django.contrib.sites.shortcuts import get_current_site
 | 
					from django.contrib.sites.shortcuts import get_current_site
 | 
				
			||||||
from django.core.mail import EmailMultiAlternatives
 | 
					from django.core.mail import EmailMultiAlternatives
 | 
				
			||||||
| 
						 | 
					@ -82,9 +83,9 @@ class UserCreationForm(forms.ModelForm):
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = UserModel
 | 
					        model = User
 | 
				
			||||||
        fields = (UserModel.USERNAME_FIELD,)
 | 
					        fields = ("username",)
 | 
				
			||||||
        field_classes = {UserModel.USERNAME_FIELD: UsernameField}
 | 
					        field_classes = {'username': UsernameField}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
| 
						 | 
					@ -131,9 +132,9 @@ class UserChangeForm(forms.ModelForm):
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = UserModel
 | 
					        model = User
 | 
				
			||||||
        fields = '__all__'
 | 
					        fields = '__all__'
 | 
				
			||||||
        field_classes = {UserModel.USERNAME_FIELD: UsernameField}
 | 
					        field_classes = {'username': UsernameField}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
        super().__init__(*args, **kwargs)
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -814,20 +814,11 @@ are working with.
 | 
				
			||||||
The following forms are compatible with any subclass of
 | 
					The following forms are compatible with any subclass of
 | 
				
			||||||
:class:`~django.contrib.auth.models.AbstractBaseUser`:
 | 
					:class:`~django.contrib.auth.models.AbstractBaseUser`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* :class:`~django.contrib.auth.forms.AuthenticationForm`
 | 
					* :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`
 | 
				
			||||||
* :class:`~django.contrib.auth.forms.PasswordChangeForm`
 | 
					* :class:`~django.contrib.auth.forms.PasswordChangeForm`
 | 
				
			||||||
* :class:`~django.contrib.auth.forms.AdminPasswordChangeForm`
 | 
					* :class:`~django.contrib.auth.forms.AdminPasswordChangeForm`
 | 
				
			||||||
* :class:`~django.contrib.auth.forms.UserCreationForm`
 | 
					 | 
				
			||||||
* :class:`~django.contrib.auth.forms.UserChangeForm`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The forms that handle a username use the username field specified by
 | 
					 | 
				
			||||||
:attr:`~models.CustomUser.USERNAME_FIELD`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.. versionchanged:: 2.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    In older versions, ``UserCreationForm`` and ``UserChangeForm`` need to be
 | 
					 | 
				
			||||||
    rewritten to work with custom user models.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
The following forms make assumptions about the user model and can be used as-is
 | 
					The following forms make assumptions about the user model and can be used as-is
 | 
				
			||||||
if those assumptions are met:
 | 
					if those assumptions are met:
 | 
				
			||||||
| 
						 | 
					@ -838,6 +829,25 @@ if those assumptions are met:
 | 
				
			||||||
  default) that can be used to identify the user and a boolean field named
 | 
					  default) that can be used to identify the user and a boolean field named
 | 
				
			||||||
  ``is_active`` to prevent password resets for inactive users.
 | 
					  ``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`
 | 
				
			||||||
--------------------------------------------
 | 
					--------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1508,12 +1508,9 @@ provides several built-in forms located in :mod:`django.contrib.auth.forms`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    A :class:`~django.forms.ModelForm` for creating a new user.
 | 
					    A :class:`~django.forms.ModelForm` for creating a new user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    It has three fields: one named after the
 | 
					    It has three fields: ``username`` (from the user model), ``password1``,
 | 
				
			||||||
    :attr:`~django.contrib.auth.models.CustomUser.USERNAME_FIELD` from the
 | 
					    and ``password2``. It verifies that ``password1`` and ``password2`` match,
 | 
				
			||||||
    user model, and ``password1`` and ``password2``.
 | 
					    validates the password using
 | 
				
			||||||
 | 
					 | 
				
			||||||
    It verifies that ``password1`` and ``password2`` match, validates the
 | 
					 | 
				
			||||||
    password using
 | 
					 | 
				
			||||||
    :func:`~django.contrib.auth.password_validation.validate_password`, and
 | 
					    :func:`~django.contrib.auth.password_validation.validate_password`, and
 | 
				
			||||||
    sets the user's password using
 | 
					    sets the user's password using
 | 
				
			||||||
    :meth:`~django.contrib.auth.models.User.set_password()`.
 | 
					    :meth:`~django.contrib.auth.models.User.set_password()`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,7 @@
 | 
				
			||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
from importlib import reload
 | 
					 | 
				
			||||||
from unittest import mock
 | 
					from unittest import mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import django
 | 
					 | 
				
			||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
from django.contrib.auth.forms import (
 | 
					from django.contrib.auth.forms import (
 | 
				
			||||||
    AdminPasswordChangeForm, AuthenticationForm, PasswordChangeForm,
 | 
					    AdminPasswordChangeForm, AuthenticationForm, PasswordChangeForm,
 | 
				
			||||||
| 
						 | 
					@ -13,7 +11,7 @@ from django.contrib.auth.forms import (
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
from django.contrib.auth.signals import user_login_failed
 | 
					from django.contrib.auth.signals import user_login_failed
 | 
				
			||||||
from django.contrib.sites.models import Site
 | 
					from django.contrib.sites.models import Site
 | 
				
			||||||
from django.core import mail, signals
 | 
					from django.core import mail
 | 
				
			||||||
from django.core.mail import EmailMultiAlternatives
 | 
					from django.core.mail import EmailMultiAlternatives
 | 
				
			||||||
from django.forms.fields import CharField, Field, IntegerField
 | 
					from django.forms.fields import CharField, Field, IntegerField
 | 
				
			||||||
from django.test import SimpleTestCase, TestCase, override_settings
 | 
					from django.test import SimpleTestCase, TestCase, override_settings
 | 
				
			||||||
| 
						 | 
					@ -29,24 +27,6 @@ from .models.with_integer_username import IntegerUsernameUser
 | 
				
			||||||
from .settings import AUTH_TEMPLATES
 | 
					from .settings import AUTH_TEMPLATES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def reload_auth_forms(sender, setting, value, enter, **kwargs):
 | 
					 | 
				
			||||||
    if setting == 'AUTH_USER_MODEL':
 | 
					 | 
				
			||||||
        reload(django.contrib.auth.forms)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ReloadFormsMixin:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def setUpClass(cls):
 | 
					 | 
				
			||||||
        super().setUpClass()
 | 
					 | 
				
			||||||
        signals.setting_changed.connect(reload_auth_forms)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @classmethod
 | 
					 | 
				
			||||||
    def tearDownClass(cls):
 | 
					 | 
				
			||||||
        signals.setting_changed.disconnect(reload_auth_forms)
 | 
					 | 
				
			||||||
        super().tearDownClass()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class TestDataMixin:
 | 
					class TestDataMixin:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
| 
						 | 
					@ -57,10 +37,9 @@ class TestDataMixin:
 | 
				
			||||||
        cls.u4 = User.objects.create(username='empty_password', password='')
 | 
					        cls.u4 = User.objects.create(username='empty_password', password='')
 | 
				
			||||||
        cls.u5 = User.objects.create(username='unmanageable_password', password='$')
 | 
					        cls.u5 = User.objects.create(username='unmanageable_password', password='$')
 | 
				
			||||||
        cls.u6 = User.objects.create(username='unknown_password', password='foo$bar')
 | 
					        cls.u6 = User.objects.create(username='unknown_password', password='foo$bar')
 | 
				
			||||||
        cls.u7 = ExtensionUser.objects.create(username='extension_client', date_of_birth='1998-02-24')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UserCreationFormTest(ReloadFormsMixin, TestDataMixin, TestCase):
 | 
					class UserCreationFormTest(TestDataMixin, TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_user_already_exists(self):
 | 
					    def test_user_already_exists(self):
 | 
				
			||||||
        data = {
 | 
					        data = {
 | 
				
			||||||
| 
						 | 
					@ -196,12 +175,9 @@ class UserCreationFormTest(ReloadFormsMixin, TestDataMixin, TestCase):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_custom_form(self):
 | 
					    def test_custom_form(self):
 | 
				
			||||||
        with override_settings(AUTH_USER_MODEL='auth_tests.ExtensionUser'):
 | 
					 | 
				
			||||||
            from django.contrib.auth.forms import UserCreationForm
 | 
					 | 
				
			||||||
            self.assertEqual(UserCreationForm.Meta.model, ExtensionUser)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        class CustomUserCreationForm(UserCreationForm):
 | 
					        class CustomUserCreationForm(UserCreationForm):
 | 
				
			||||||
            class Meta(UserCreationForm.Meta):
 | 
					            class Meta(UserCreationForm.Meta):
 | 
				
			||||||
 | 
					                model = ExtensionUser
 | 
				
			||||||
                fields = UserCreationForm.Meta.fields + ('date_of_birth',)
 | 
					                fields = UserCreationForm.Meta.fields + ('date_of_birth',)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data = {
 | 
					        data = {
 | 
				
			||||||
| 
						 | 
					@ -212,9 +188,6 @@ class UserCreationFormTest(ReloadFormsMixin, TestDataMixin, TestCase):
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        form = CustomUserCreationForm(data)
 | 
					        form = CustomUserCreationForm(data)
 | 
				
			||||||
        self.assertTrue(form.is_valid())
 | 
					        self.assertTrue(form.is_valid())
 | 
				
			||||||
        # reload_auth_forms() reloads the form.
 | 
					 | 
				
			||||||
        from django.contrib.auth.forms import UserCreationForm
 | 
					 | 
				
			||||||
        self.assertEqual(UserCreationForm.Meta.model, User)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_custom_form_with_different_username_field(self):
 | 
					    def test_custom_form_with_different_username_field(self):
 | 
				
			||||||
        class CustomUserCreationForm(UserCreationForm):
 | 
					        class CustomUserCreationForm(UserCreationForm):
 | 
				
			||||||
| 
						 | 
					@ -288,30 +261,6 @@ class UserCreationFormTest(ReloadFormsMixin, TestDataMixin, TestCase):
 | 
				
			||||||
            ['The password is too similar to the first name.'],
 | 
					            ['The password is too similar to the first name.'],
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_with_custom_user_model(self):
 | 
					 | 
				
			||||||
        with override_settings(AUTH_USER_MODEL='auth_tests.ExtensionUser'):
 | 
					 | 
				
			||||||
            data = {
 | 
					 | 
				
			||||||
                'username': 'test_username',
 | 
					 | 
				
			||||||
                'password1': 'test_password',
 | 
					 | 
				
			||||||
                'password2': 'test_password',
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            from django.contrib.auth.forms import UserCreationForm
 | 
					 | 
				
			||||||
            self.assertEqual(UserCreationForm.Meta.model, ExtensionUser)
 | 
					 | 
				
			||||||
            form = UserCreationForm(data)
 | 
					 | 
				
			||||||
            self.assertTrue(form.is_valid())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_customer_user_model_with_different_username_field(self):
 | 
					 | 
				
			||||||
        with override_settings(AUTH_USER_MODEL='auth_tests.CustomUser'):
 | 
					 | 
				
			||||||
            from django.contrib.auth.forms import UserCreationForm
 | 
					 | 
				
			||||||
            self.assertEqual(UserCreationForm.Meta.model, CustomUser)
 | 
					 | 
				
			||||||
            data = {
 | 
					 | 
				
			||||||
                'email': 'testchange@test.com',
 | 
					 | 
				
			||||||
                'password1': 'test_password',
 | 
					 | 
				
			||||||
                'password2': 'test_password',
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            form = UserCreationForm(data)
 | 
					 | 
				
			||||||
            self.assertTrue(form.is_valid())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# To verify that the login form rejects inactive users, use an authentication
 | 
					# To verify that the login form rejects inactive users, use an authentication
 | 
				
			||||||
# backend that allows them.
 | 
					# backend that allows them.
 | 
				
			||||||
| 
						 | 
					@ -677,7 +626,7 @@ class PasswordChangeFormTest(TestDataMixin, TestCase):
 | 
				
			||||||
        self.assertEqual(form.cleaned_data['new_password2'], data['new_password2'])
 | 
					        self.assertEqual(form.cleaned_data['new_password2'], data['new_password2'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UserChangeFormTest(ReloadFormsMixin, TestDataMixin, TestCase):
 | 
					class UserChangeFormTest(TestDataMixin, TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_username_validity(self):
 | 
					    def test_username_validity(self):
 | 
				
			||||||
        user = User.objects.get(username='testclient')
 | 
					        user = User.objects.get(username='testclient')
 | 
				
			||||||
| 
						 | 
					@ -751,51 +700,22 @@ class UserChangeFormTest(ReloadFormsMixin, TestDataMixin, TestCase):
 | 
				
			||||||
        self.assertEqual(form.initial['password'], form['password'].value())
 | 
					        self.assertEqual(form.initial['password'], form['password'].value())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_custom_form(self):
 | 
					    def test_custom_form(self):
 | 
				
			||||||
        with override_settings(AUTH_USER_MODEL='auth_tests.ExtensionUser'):
 | 
					 | 
				
			||||||
            from django.contrib.auth.forms import UserChangeForm
 | 
					 | 
				
			||||||
            self.assertEqual(UserChangeForm.Meta.model, ExtensionUser)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        class CustomUserChangeForm(UserChangeForm):
 | 
					        class CustomUserChangeForm(UserChangeForm):
 | 
				
			||||||
            class Meta(UserChangeForm.Meta):
 | 
					            class Meta(UserChangeForm.Meta):
 | 
				
			||||||
                    fields = ('username', 'password', 'date_of_birth')
 | 
					                model = ExtensionUser
 | 
				
			||||||
 | 
					                fields = ('username', 'password', 'date_of_birth',)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        user = User.objects.get(username='testclient')
 | 
				
			||||||
        data = {
 | 
					        data = {
 | 
				
			||||||
            'username': 'testclient',
 | 
					            'username': 'testclient',
 | 
				
			||||||
            'password': 'testclient',
 | 
					            'password': 'testclient',
 | 
				
			||||||
            'date_of_birth': '1998-02-24',
 | 
					            'date_of_birth': '1998-02-24',
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
            form = CustomUserChangeForm(data, instance=self.u7)
 | 
					        form = CustomUserChangeForm(data, instance=user)
 | 
				
			||||||
        self.assertTrue(form.is_valid())
 | 
					        self.assertTrue(form.is_valid())
 | 
				
			||||||
        form.save()
 | 
					        form.save()
 | 
				
			||||||
        self.assertEqual(form.cleaned_data['username'], 'testclient')
 | 
					        self.assertEqual(form.cleaned_data['username'], 'testclient')
 | 
				
			||||||
        self.assertEqual(form.cleaned_data['date_of_birth'], datetime.date(1998, 2, 24))
 | 
					        self.assertEqual(form.cleaned_data['date_of_birth'], datetime.date(1998, 2, 24))
 | 
				
			||||||
        # reload_auth_forms() reloads the form.
 | 
					 | 
				
			||||||
        from django.contrib.auth.forms import UserChangeForm
 | 
					 | 
				
			||||||
        self.assertEqual(UserChangeForm.Meta.model, User)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_with_custom_user_model(self):
 | 
					 | 
				
			||||||
        with override_settings(AUTH_USER_MODEL='auth_tests.ExtensionUser'):
 | 
					 | 
				
			||||||
            from django.contrib.auth.forms import UserChangeForm
 | 
					 | 
				
			||||||
            self.assertEqual(UserChangeForm.Meta.model, ExtensionUser)
 | 
					 | 
				
			||||||
            data = {
 | 
					 | 
				
			||||||
                'username': 'testclient',
 | 
					 | 
				
			||||||
                'date_joined': '1998-02-24',
 | 
					 | 
				
			||||||
                'date_of_birth': '1998-02-24',
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            form = UserChangeForm(data, instance=self.u7)
 | 
					 | 
				
			||||||
            self.assertTrue(form.is_valid())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_customer_user_model_with_different_username_field(self):
 | 
					 | 
				
			||||||
        with override_settings(AUTH_USER_MODEL='auth_tests.CustomUser'):
 | 
					 | 
				
			||||||
            from django.contrib.auth.forms import UserChangeForm
 | 
					 | 
				
			||||||
            self.assertEqual(UserChangeForm.Meta.model, CustomUser)
 | 
					 | 
				
			||||||
            user = CustomUser.custom_objects.create(email='test@test.com', date_of_birth='1998-02-24')
 | 
					 | 
				
			||||||
            data = {
 | 
					 | 
				
			||||||
                'email': 'testchange@test.com',
 | 
					 | 
				
			||||||
                'date_of_birth': '1998-02-24',
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            form = UserChangeForm(data, instance=user)
 | 
					 | 
				
			||||||
            self.assertTrue(form.is_valid())
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_password_excluded(self):
 | 
					    def test_password_excluded(self):
 | 
				
			||||||
        class UserChangeFormWithoutPassword(UserChangeForm):
 | 
					        class UserChangeFormWithoutPassword(UserChangeForm):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue