2

I'm using Django 1.9, where usernames have a 30 character limit. In order to overcome this, I created a custom user model as such:

class User(AbstractUser): pass # Override username max_length to allow long usernames. User._meta.get_field('username').max_length = 255 User._meta.get_field('username').help_text = _( 'Required. 255 characters or fewer. Letters, digits and @/./+/-/_ only.') 

In the shell I can create users with names longer than 30 characters, but in the admin I cannot add users with long usernames or assign long usernames to existing users. I get:

Ensure this value has at most 30 characters (it has 43).

I noticed that Django Admin's UserCreateForm and UserChangeForm have Django's default User model explicitly set in their Meta options (which shouldn't be the case, there's a ticket regarding this), so I used custom forms like this:

from django.contrib.auth import get_user_model from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import UserCreationForm, UserChangeForm User = get_user_model() class CustomUserCreationForm(UserCreationForm): class Meta(UserCreationForm.Meta): model = User class CustomUserChangeForm(UserChangeForm): class Meta(UserChangeForm.Meta): model = User class CustomUserAdmin(UserAdmin): form = CustomUserChangeForm add_form = CustomUserCreationForm 

Still it didn't work. So I added a breakpoint to the CustomUserChangeForm's init, after calling super, and I got:

ipdb> self <UserForm bound=True, valid=False, fields=(username;password;first_name;last_name;email;is_active;is_staff;is_superuser;groups;user_permissions)> ipdb> self._meta.model <class 'custom.models.User'> ipdb> self.fields['username'].max_length 255 ipdb> self.fields['username'].validators[0].limit_value 255 ipdb> self.fields['username'].clean('a_username_with_more_than_thirty_characters') u'a_username_with_more_than_thirty_characters' ipdb> self.errors {'username': [u'Ensure this value has at most 30 characters (it has 38).']} 

I am mind blown. I don't know what I could possibly be missing. Any ideas?

2
  • Did you set the AUTH_USER_MODEL setting? Commented Sep 17, 2018 at 15:47
  • Yes, and I checked in the debugger that the form was using the correct model. I edited the question and added this check. Commented Sep 18, 2018 at 6:48

2 Answers 2

2

Ok, I found out what the problem was. When Django's default username field is instantiated, it adds a MaxLengthValidator to its list of validators and uses the max_length argument to set its limit_value. When I monkey patched the User class, I overwrote the max_length and help_text of the username field, but I didn't take care of the validator. Adding this line under my custom User class fixed the issue:

User._meta.get_field('username').validators[1].limit_value = 255 

The amount of time I spent debugging this is probably a good illustration of how monkey patching is usually a bad idea.

Sign up to request clarification or add additional context in comments.

Comments

1

In other way, you can use your own custom model and fields with AbstractBaseUser.

from django.contrib.auth.models import AbstractBaseUser class User(AbstractBaseUser): my_new_username = models.CharField(unique=True, max_length=50, verbose_name="Username") USERNAME_FIELD = 'my_new_username' 

And the differences between AbstractBaseUser and AbstractUser explained here. Also there is other answer that might be help you.

1 Comment

I know, but it just seemed so tedious to go through all that configuration, explicitly configuring Django to use values that would have been the default anyway, just so I can change the max_length of the username… That's why I preferred to just inherit from AbstractUser directly. I don't understand why it shouldn't work the way I did it.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.