从标准Django模型中删除字段

时间:2011-11-23 22:16:25

标签: django model del

注意:这是在AbstractUser存在之前询问的,这可能是您最近想要使用的内容。

基本上我想从默认的Django User类中删除默认的电子邮件字段...

class MyUser(User):
    field = models.CharField(max_length = 10)
    a = 'hello'
    def b(self):
        print 'world'

del User.email
del MyUser.email
del Myuser.field

所有这些都给出了AttributeError。以下列方式删除方法或属性虽然可以正常工作:

del MyUser.a
del MyUser.b

所以我很好奇为什么这不起作用;这些模型领域是什么类型的东西?

我尝试的另一件事是通过在MyUser中创建一个email = None覆盖电子邮件,但这也不起作用(并且会稍微丑陋)。

提前致谢!

P.S。如果你想知道为什么;它更多的是好奇而不是应用程序真正需要...但我认为不要在数据库中使用未使用的列是好的。 P.p.s.我不想更改Django文件以手动删除用户的“电子邮件”。

编辑:此处有跟进问题(对于那些想要做同样事情的人)Before syncdb, delete field from standard Django model

2 个答案:

答案 0 :(得分:7)

正如您所发现的,模型字段实际上并不是类属性,即使它们看起来像是。

模型由一些非常聪明但复杂的黑客攻击构建。执行模型类定义时(第一次导入其models.py),元类会遍历该模型的所有字段定义,并调用每个模型的contribute_to_class方法。这最终将实际字段放入新类的_meta.fields属性中。因此模型类本身没有直接属性字段。

然后,当实际实例化模型实例时,Django使用该列表并使用构造函数的参数或字段提供的默认值直接设置新实例的属性。因此,通过实例访问的值后面没有实际的字段代码:它是一个简单的实例属性。

无论如何,所有这一切的结果是要从模型定义中删除字段,您只需要从Model._meta.fields列表中删除它。

答案 1 :(得分:0)

由于Model._meta.fields是不可变的列表,因此您将无法直接对其进行更改。

但是,您可以像这样修改local_fields

def remove_field(model_cls, field_name):
    for field in model_cls._meta.local_fields:
        if field.name == field_name:
            model_cls._meta.local_fields.remove(field)

remove_field(User, "email")