有一种方法可以在不触及核心模型和继承的情况下实现这一点,但这绝对是 hackish,我会格外小心地使用它。
如果您查看 Django 的有关信号的文档,您会看到一个称为的文档class_prepared
,它基本上是在元类创建任何实际模型类后发送的。那一刻是您在任何魔法发生之前修改任何模型的最后机会(即: ModelForm
、ModelAdmin
、syncdb
等...)。
所以计划很简单,您只需将该信号注册到一个处理程序,该处理程序将检测何时为User
模型调用它,然后更改该字段的max_length
属性。username
现在的问题是,这段代码应该放在哪里?它必须在User
模型加载之前执行,所以这通常意味着非常早。不幸的是,你不能(django 1.1.1,还没有检查另一个版本)把它放进去,settings
因为在那里导入signals
会破坏事情。
更好的选择是将它放在一个虚拟应用程序的模型模块中,并将该应用程序放在INSTALLED_APPS
列表/元组的顶部(这样它就会在其他任何东西之前被导入)。这是您可以拥有的示例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
字段的,以反映新的最大长度
- 如果要使用自动管理,则必须进行子类化
UserChangeForm
,UserCreationForm
并且AuthenticationForm
最大长度不是从模型字段中推导出来的,而是直接在表单字段声明中。
如果您使用South,您可以创建以下迁移来更改基础数据库中的列:
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