如何在Django中覆盖用户名max_length?

时间:2018-09-17 15:39:52

标签: python django django-forms django-admin

我正在使用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.')

在shell中,我可以创建名称长度超过30个字符的用户,但是在admin中,我无法添加具有长用户名的用户或为现有用户分配长用户名。我得到:

  

确保此值最多包含30个字符(最大为43个字符)。

我注意到Django Admin的UserCreateForm和UserChangeForm在其Meta选项中明确设置了Django的默认用户模型(不应该这样,有一个ticket),所以我使用了如下的自定义形式:

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

仍然没有用。因此,在调用super之后,我在CustomUserChangeForm的init中添加了一个断点,得到了:

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 :(得分:1)

通过其他方式,您可以将自己的自定义模型和字段与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'

AbstractBaseUserAbstractUser之间的差异解释了here。还有other answer可能会对您有所帮助。

答案 1 :(得分:0)

好的,我发现了问题所在。实例化Django的默认username字段时,它将在其验证器列表中添加MaxLengthValidator并使用max_length参数设置其limit_value。当我修补User类时,我改写了max_length字段的help_textusername,但是我没有处理验证器。在我的自定义User类下添加以下行可解决此问题:

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

我花了很多时间进行调试,这可能很好地说明了猴子修补通常是个坏主意。