Commit 849538d0 authored by Yin Jifeng's avatar Yin Jifeng Committed by Tim Graham
Browse files

Fixed #13147 -- Moved User validation logic from form to model.

parent d8833366
Loading
Loading
Loading
Loading
+0 −28
Original line number Diff line number Diff line
@@ -74,16 +74,8 @@ class UserCreationForm(forms.ModelForm):
    password.
    """
    error_messages = {
        'duplicate_username': _("A user with that username already exists."),
        'password_mismatch': _("The two password fields didn't match."),
    }
    username = forms.RegexField(label=_("Username"), max_length=30,
        regex=r'^[\w.@+-]+$',
        help_text=_("Required. 30 characters or fewer. Letters, digits and "
                    "@/./+/-/_ only."),
        error_messages={
            'invalid': _("This value may contain only letters, numbers and "
                         "@/./+/-/_ characters.")})
    password1 = forms.CharField(label=_("Password"),
        widget=forms.PasswordInput)
    password2 = forms.CharField(label=_("Password confirmation"),
@@ -94,19 +86,6 @@ class UserCreationForm(forms.ModelForm):
        model = User
        fields = ("username",)

    def clean_username(self):
        # Since User.username is unique, this check is redundant,
        # but it sets a nicer error message than the ORM. See #13147.
        username = self.cleaned_data["username"]
        try:
            User._default_manager.get(username=username)
        except User.DoesNotExist:
            return username
        raise forms.ValidationError(
            self.error_messages['duplicate_username'],
            code='duplicate_username',
        )

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
@@ -126,13 +105,6 @@ class UserCreationForm(forms.ModelForm):


class UserChangeForm(forms.ModelForm):
    username = forms.RegexField(
        label=_("Username"), max_length=30, regex=r"^[\w.@+-]+$",
        help_text=_("Required. 30 characters or fewer. Letters, digits and "
                    "@/./+/-/_ only."),
        error_messages={
            'invalid': _("This value may contain only letters, numbers and "
                         "@/./+/-/_ characters.")})
    password = ReadOnlyPasswordHashField(label=_("Password"),
        help_text=_("Raw passwords are not stored, so there is no way to see "
                    "this user's password, but you can change the password "
+8 −2
Original line number Diff line number Diff line
@@ -383,8 +383,14 @@ class AbstractUser(AbstractBaseUser, PermissionsMixin):
        help_text=_('Required. 30 characters or fewer. Letters, digits and '
                    '@/./+/-/_ only.'),
        validators=[
            validators.RegexValidator(r'^[\w.@+-]+$', _('Enter a valid username.'), 'invalid')
        ])
            validators.RegexValidator(r'^[\w.@+-]+$',
                                      _('Enter a valid username. '
                                        'This value may contain only letters, numbers '
                                        'and @/./+/-/_ characters.'), 'invalid'),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        })
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), blank=True)
+6 −8
Original line number Diff line number Diff line
@@ -4,7 +4,6 @@ import os
import re

from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
from django.contrib.auth.forms import (UserCreationForm, AuthenticationForm,
    PasswordChangeForm, SetPasswordForm, UserChangeForm, PasswordResetForm,
@@ -36,7 +35,7 @@ class UserCreationFormTest(TestCase):
        form = UserCreationForm(data)
        self.assertFalse(form.is_valid())
        self.assertEqual(form["username"].errors,
                         [force_text(form.error_messages['duplicate_username'])])
                         [force_text(User._meta.get_field('username').error_messages['unique'])])

    def test_invalid_data(self):
        data = {
@@ -46,8 +45,8 @@ class UserCreationFormTest(TestCase):
        }
        form = UserCreationForm(data)
        self.assertFalse(form.is_valid())
        self.assertEqual(form["username"].errors,
                         [force_text(form.fields['username'].error_messages['invalid'])])
        validator = next(v for v in User._meta.get_field('username').validators if v.code == 'invalid')
        self.assertEqual(form["username"].errors, [force_text(validator.message)])

    def test_password_verification(self):
        # The verification password is incorrect.
@@ -190,8 +189,7 @@ class AuthenticationFormTest(TestCase):
            username = CharField()

        form = CustomAuthenticationForm()
        UserModel = get_user_model()
        username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD)
        username_field = User._meta.get_field(User.USERNAME_FIELD)
        self.assertEqual(form.fields['username'].label, capfirst(username_field.verbose_name))

    def test_username_field_label_empty_string(self):
@@ -291,8 +289,8 @@ class UserChangeFormTest(TestCase):
        data = {'username': 'not valid'}
        form = UserChangeForm(data, instance=user)
        self.assertFalse(form.is_valid())
        self.assertEqual(form['username'].errors,
                         [force_text(form.fields['username'].error_messages['invalid'])])
        validator = next(v for v in User._meta.get_field('username').validators if v.code == 'invalid')
        self.assertEqual(form["username"].errors, [force_text(validator.message)])

    def test_bug_14242(self):
        # A regression test, introduce by adding an optimization for the
+4 −0
Original line number Diff line number Diff line
@@ -414,6 +414,10 @@ Miscellaneous
  parameters. Internally, Django will continue to provide the
  ``pk`` parameter in ``params`` for backwards compatibility.

* ``UserCreationForm.errors_messages['duplicate_username']`` is no longer used.
  If you wish to customize that error message, use
  ``User.error_messages['unique']`` instead.

.. _deprecated-features-1.8:

Features deprecated in 1.8