Browse Source

Fixed #26719 -- Normalized email in AbstractUser.clean().

Bang Dao + Tam Huynh 8 năm trước cách đây
mục cha
commit
09119dff14

+ 4 - 0
django/contrib/auth/models.py

@@ -344,6 +344,10 @@ class AbstractUser(AbstractBaseUser, PermissionsMixin):
         verbose_name_plural = _('users')
         abstract = True
 
+    def clean(self):
+        super(AbstractUser, self).clean()
+        self.email = self.__class__.objects.normalize_email(self.email)
+
     def get_full_name(self):
         """
         Returns the first_name plus the last_name, with a space in between.

+ 5 - 0
docs/releases/1.11.txt

@@ -293,6 +293,11 @@ Miscellaneous
   <django.db.models.Model.validate_unique>` no longer checks empty strings for
   uniqueness as the database interprets the value as ``NULL``.
 
+* If you subclass :class:`.AbstractUser` and override ``clean()``, be sure it
+  calls ``super()``. :meth:`.BaseUserManager.normalize_email` is called in a
+  new :meth:`.AbstractUser.clean` method so that normalization is applied in
+  cases like model form validation.
+
 .. _deprecated-features-1.11:
 
 Features deprecated in 1.11

+ 13 - 1
docs/topics/auth/customizing.txt

@@ -692,6 +692,18 @@ The following attributes and methods are available on any subclass of
         Returns an HMAC of the password field. Used for
         :ref:`session-invalidation-on-password-change`.
 
+:class:`~models.AbstractUser` subclasses :class:`~models.AbstractBaseUser`:
+
+.. class:: models.AbstractUser
+
+    .. method:: clean()
+
+        .. versionadded:: 1.11
+
+        Normalizes the email by calling
+        :meth:`.BaseUserManager.normalize_email`. If you override this method,
+        be sure to call ``super()`` to retain the normalization.
+
 You should also define a custom manager for your ``User`` model. If your
 ``User`` model defines ``username``, ``email``, ``is_staff``, ``is_active``,
 ``is_superuser``, ``last_login``, and ``date_joined`` fields the same as
@@ -759,7 +771,7 @@ Extending Django's default ``User``
 
 If you're entirely happy with Django's :class:`~django.contrib.auth.models.User`
 model and you just want to add some additional profile information, you could
-simply subclass ``django.contrib.auth.models.AbstractUser`` and add your
+simply subclass :class:`django.contrib.auth.models.AbstractUser` and add your
 custom profile fields, although we'd recommend a separate model as described in
 the "Model design considerations" note of :ref:`specifying-custom-user-model`.
 ``AbstractUser`` provides the full implementation of the default

+ 5 - 0
tests/auth_tests/test_models.py

@@ -194,6 +194,11 @@ class AbstractUserTestCase(TestCase):
         user2 = User.objects.create_user(username='user2')
         self.assertIsNone(user2.last_login)
 
+    def test_user_clean_normalize_email(self):
+        user = User(username='user', password='foo', email='foo@BAR.com')
+        user.clean()
+        self.assertEqual(user.email, 'foo@bar.com')
+
     def test_user_double_save(self):
         """
         Calling user.save() twice should trigger password_changed() once.