有一种方法可以在不触及核心模型且不使用继承的情况下实现,但这显然是hackish的,我建议小心使用。
如果你查看Django文档关于信号,你会发现有一个叫做class_prepared
的信号,它基本上是在任何实际的模型类被元类创建后发送的。那个时刻是在任何魔术发生之前修改任何模型的最后机会(例如:ModelForm
,ModelAdmin
,syncdb
等)。
所以计划很简单,你只需要注册该信号与处理程序,以便检测是否对User
模型调用它,然后更改username
字段的max_length
属性。
现在问题是,这段代码应该放在哪里?它必须在加载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):
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):
db.alter_column('auth_user', 'username', models.CharField(max_length=75))
def backwards(self, orm):
db.alter_column('auth_user', 'username', models.CharField(max_length=35))
models = {
auth.contrib
的冗长抱怨。你将其编辑得更文明了,但是 Stack Overflow 声称“投票时间过久,无法更改”。 - T. Stone