summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBang Dao + Tam Huynh <bang.dao+tam.huynh@eastagile.com>2016-06-16 17:06:59 +0700
committerTim Graham <timograham@gmail.com>2016-06-24 10:37:38 -0400
commit09119dff14ad24d53ac0273e5cd2de24de0b0d81 (patch)
treec3501f95b837ec7c497270adfb369b3ec10f672e
parent7e303d15c349401f54761a616acdb20924600da9 (diff)
Fixed #26719 -- Normalized email in AbstractUser.clean().
-rw-r--r--django/contrib/auth/models.py4
-rw-r--r--docs/releases/1.11.txt5
-rw-r--r--docs/topics/auth/customizing.txt14
-rw-r--r--tests/auth_tests/test_models.py5
4 files changed, 27 insertions, 1 deletions
diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py
index 4812546340..725563424a 100644
--- a/django/contrib/auth/models.py
+++ b/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.
diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt
index ca54d0b223..e5dcc47e24 100644
--- a/docs/releases/1.11.txt
+++ b/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
diff --git a/docs/topics/auth/customizing.txt b/docs/topics/auth/customizing.txt
index 75dd4160d0..db18bfb8c2 100644
--- a/docs/topics/auth/customizing.txt
+++ b/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
diff --git a/tests/auth_tests/test_models.py b/tests/auth_tests/test_models.py
index 7967306c43..5f66a48141 100644
--- a/tests/auth_tests/test_models.py
+++ b/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.