Как переопределить имя пользователя max_length в Django? - PullRequest
0 голосов
/ 17 сентября 2018

Я использую Django 1.9, где имена пользователей имеют ограничение в 30 символов. Чтобы преодолеть это, я создал пользовательскую модель как таковую:

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.')

В оболочке я могу создавать пользователей с именами длиннее 30 символов, но в админе я не могу добавлять пользователей с длинными именами или назначать длинные имена существующим пользователям. Я получаю:

Убедитесь, что это значение содержит не более 30 символов (у него 43).

Я заметил, что UserCreateForm и UserChangeForm в Django Admin имеют стандартную пользовательскую модель Django, явно заданную в их мета-опциях (чего не должно быть, в этом есть тикет ), поэтому я использовал такие пользовательские формы, как это:

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

Тем не менее, это не сработало. Поэтому я добавил точку останова в init CustomUserChangeForm после вызова super и получил:

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).']}

Я сумасшедший. Я не знаю, чего мне не хватает. Есть идеи?

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Хорошо, я выяснил, в чем проблема.Когда создается экземпляр поля username по умолчанию в Django, он добавляет MaxLengthValidator в свой список валидаторов и использует аргумент max_length для установки limit_value.Когда я установил исправление для класса User, я перезаписал поля max_length и help_text поля username, но не позаботился о валидаторе.Добавление этой строки в мой пользовательский класс User устранило проблему:

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

Количество времени, которое я потратил на отладку, вероятно, является хорошей иллюстрацией того, как исправление обезьян обычно является плохой идеей.

0 голосов
/ 18 сентября 2018

Другими словами, вы можете использовать собственную модель и поля с 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'

И различия между AbstractBaseUser и AbstractUser объясняются здесь . Также есть другой ответ , который может вам помочь.

...