diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index 42addc190e..6b9d2dd7b8 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -137,10 +137,12 @@ class UserChangeForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.fields['password'].help_text = self.fields['password'].help_text.format('../password/') - f = self.fields.get('user_permissions') - if f is not None: - f.queryset = f.queryset.select_related('content_type') + password = self.fields.get('password') + if password: + password.help_text = password.help_text.format('../password/') + user_permissions = self.fields.get('user_permissions') + if user_permissions: + user_permissions.queryset = user_permissions.queryset.select_related('content_type') def clean_password(self): # Regardless of what the user provides, return the initial value. diff --git a/tests/auth_tests/test_forms.py b/tests/auth_tests/test_forms.py index b1d55c9749..32b2173996 100644 --- a/tests/auth_tests/test_forms.py +++ b/tests/auth_tests/test_forms.py @@ -797,6 +797,17 @@ class UserChangeFormTest(ReloadFormsMixin, TestDataMixin, TestCase): form = UserChangeForm(data, instance=user) self.assertTrue(form.is_valid()) + def test_password_excluded(self): + class UserChangeFormWithoutPassword(UserChangeForm): + password = None + + class Meta: + model = User + exclude = ['password'] + + form = UserChangeFormWithoutPassword() + self.assertNotIn('password', form.fields) + @override_settings(TEMPLATES=AUTH_TEMPLATES) class PasswordResetFormTest(TestDataMixin, TestCase):