django 的 auth_user.username 可以是 varchar(75) 吗?那怎么可能呢? [英] Can django's auth_user.username be varchar(75)? How could that be done?

查看:33
本文介绍了django 的 auth_user.username 可以是 varchar(75) 吗?那怎么可能呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

auth_user 上运行alter table 以使username 成为varchar(75) 以便它适合电子邮件有什么问题吗?如果有的话,那会破坏什么?

Is there anything wrong with running alter table on auth_user to make username be varchar(75) so it can fit an email? What does that break if anything?

如果您将 auth_user.username 更改为 varchar(75),您需要在哪里修改 django?是不是简单的把源码里的30改成75?

If you were to change auth_user.username to be varchar(75) where would you need to modify django? Is it simply a matter of changing 30 to 75 in the source code?

username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))

或者该字段是否有其他验证需要更改或这样做会产生任何其他影响?

Or is there other validation on this field that would have to be changed or any other repercussions to doing so?

有关这样做的原因,请参阅下面与 bartek 的评论讨论.

See comment discussion with bartek below regarding the reason for doing it.

编辑:几个月后回顾这一点.对于不知道前提的人:有些应用没有要求或不希望使用用户名,他们只使用电子邮件进行注册和使用;授权.不幸的是,在 django auth.contrib 中,需要用户名.您可以开始将电子邮件放在用户名字段中,但该字段只有 30 个字符,并且电子邮件在现实世界中可能很长.可能比此处建议的 75 个字符更长,但 75 个字符可容纳大多数正常的电子邮件地址.该问题针对的是基于电子邮件身份验证的应用程序遇到的这种情况.

Edit: Looking back on this after many months. For anyone who doesn't know the premise: Some apps don't have a requirement or desire to use a username, they use only email for registration & auth. Unfortunately in django auth.contrib, username is required. You could start putting emails in the username field, but the field is only 30 char and emails may be long in the real world. Potentially even longer than the 75 char suggested here, but 75 char accommodates most sane email addresses. The question is aimed at this situation, as encountered by email-auth-based applications.

推荐答案

有一种方法可以在不触及核心模型和继承的情况下实现这一点,但这绝对是黑客行为,我会格外小心地使用它.

There's a way to achieve that without touching the core model, and without inheritance, but it's definitely hackish and I would use it with extra care.

如果您查看 Django 的文档 关于信号,您会看到有一个叫做class_prepared,它基本上是在元类创建任何实际模型类后发送的.那一刻是您在任何魔法发生之前修改任何模型的最后机会(即:ModelFormModelAdminsyncdb>,等等...)

If you look at Django's doc on signals, you'll see there's one called class_prepared, which is basically sent once any actual model class has been created by the metaclass. That moment is your last chance of modifying any model before any magic takes place (ie: ModelForm, ModelAdmin, syncdb, etc...).

所以计划很简单,您只需将该信号注册到一个处理程序,该处理程序将检测何时为 User 模型调用它,然后更改 max_length 模型的属性username 字段.

So the plan is simple, you just register that signal with a handler that will detect when it is called for the User model, and then change the max_length property of the username field.

现在的问题是,这段代码应该放在哪里?它必须在 User 模型加载之前执行,所以这通常意味着很早.不幸的是,你不能(django 1.1.1,还没有检查另一个版本)把它放在 settings 中,因为导入 signals 会有打破东西.

Now the question is, where should this code lives? It has to be executed before the User model is loaded, so that often means very early. Unfortunately, you can't (django 1.1.1, haven't check with another version) put that in settings because importing signals there will break things.

更好的选择是将它放在一个虚拟应用程序的模型模块中,并将该应用程序放在INSTALLED_APPS列表/元组的顶部(因此它被导入在其他任何事情之前).以下是您可以在 myhackishfix_app/models.py 中拥有的示例:

A better choice would be to put it in a dummy app's models module, and to put that app on top of the INSTALLED_APPS list/tuple (so it gets imported before anything else). Here is an example of what you can have in myhackishfix_app/models.py :

from django.db.models.signals import class_prepared

def longer_username(sender, *args, **kwargs):
    # You can't just do `if sender == django.contrib.auth.models.User`
    # because you would have to import the model
    # You have to test using __name__ and __module__
    if sender.__name__ == "User" and sender.__module__ == "django.contrib.auth.models":
        sender._meta.get_field("username").max_length = 75

class_prepared.connect(longer_username)

这样就行了.

一些注意事项:

  • 您可能还想更改字段的help_text,以反映新的最大长度
  • 如果你想使用自动管理,你必须对UserChangeFormUserCreationFormAuthenticationForm进行子类化,因为没有推导出最大长度来自模型字段,但直接在表单字段声明中.
  • You might want to change also the help_text of the field, to reflect the new maximum length
  • If you want to use the automatic admin, you will have to subclass UserChangeForm, UserCreationForm and AuthenticationForm as the maximum length is not deduced from the model field, but directly in the form field declaration.

如果您使用的是 South,您可以创建以下迁移来更改底层数据库中的列:

If you're using South, you can create the following migration to change the column in the underlying database:

import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):

        # Changing field 'User.username'
        db.alter_column('auth_user', 'username', models.CharField(max_length=75))


    def backwards(self, orm):

        # Changing field 'User.username'
        db.alter_column('auth_user', 'username', models.CharField(max_length=35))


    models = { 

# ... Copy the remainder of the file from the previous migration, being sure 
# to change the value for auth.user / usename / maxlength

这篇关于django 的 auth_user.username 可以是 varchar(75) 吗?那怎么可能呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆