diff --git a/django/contrib/auth/migrations/0008_alter_user_username_max_length.py b/django/contrib/auth/migrations/0008_alter_user_username_max_length.py index 56705fa58f..2afbc30c2a 100644 --- a/django/contrib/auth/migrations/0008_alter_user_username_max_length.py +++ b/django/contrib/auth/migrations/0008_alter_user_username_max_length.py @@ -17,8 +17,8 @@ class Migration(migrations.Migration): name='username', field=models.CharField( error_messages={'unique': 'A user with that username already exists.'}, - help_text='Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.', - max_length=254, + help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', + max_length=150, unique=True, validators=[ django.core.validators.RegexValidator( diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index dfa76977d7..0600b96774 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -303,9 +303,9 @@ class AbstractUser(AbstractBaseUser, PermissionsMixin): """ username = models.CharField( _('username'), - max_length=254, + max_length=150, unique=True, - help_text=_('Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.'), + help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'), validators=[ validators.RegexValidator( r'^[\w.@+-]+$', diff --git a/docs/ref/contrib/auth.txt b/docs/ref/contrib/auth.txt index 6ca2581397..e4c31731d5 100644 --- a/docs/ref/contrib/auth.txt +++ b/docs/ref/contrib/auth.txt @@ -21,12 +21,19 @@ Fields .. attribute:: username - Required. 254 characters or fewer. Usernames may contain alphanumeric, + Required. 150 characters or fewer. Usernames may contain alphanumeric, ``_``, ``@``, ``+``, ``.`` and ``-`` characters. + The ``max_length`` should be sufficient for many use cases. If you need + a longer length, please use a :ref:`custom user model + `. If you use MySQL with the ``utf8mb4`` + encoding (recommended for proper Unicode support), specify at most + ``max_length=191`` because MySQL can only create unique indexes with + 191 characters in that case by default. + .. versionchanged:: 1.10 - The ``max_length`` increased from 30 to 254 characters. + The ``max_length`` increased from 30 to 150 characters. .. attribute:: first_name diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index cf9b67d2d0..f3c7669d8a 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -354,13 +354,20 @@ to its proxied concrete class. This inconsistency was fixed by returning the full set of fields pointing to a concrete class or one of its proxies in both cases. -:attr:`AbstractUser.username ` ``max_length`` increased to 254 +:attr:`AbstractUser.username ` ``max_length`` increased to 150 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A migration for :attr:`django.contrib.auth.models.User.username` is included. If you have a custom user model inheriting from ``AbstractUser``, you'll need to generate and apply a database migration for your user model. +We considered an increase to 254 characters to more easily allow the use of +email addresses (which are limited to 254 characters) as usernames but rejected +it due to a MySQL limitation. When using the ``utf8mb4`` encoding (recommended +for proper Unicode support), MySQL can only create unique indexes with 191 +characters by default. Therefore, if you need a longer length, please use a +custom user model. + If you want to preserve the 30 character limit for usernames, use a custom form when creating a user or changing usernames::