【问题标题】:Delete field from standard Django model从标准 Django 模型中删除字段
【发布时间】:2012-01-05 04:41:30
【问题描述】:

注意:这是在 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 来覆盖电子邮件,但这也不起作用(而且会更难看)。

提前致谢!

附:如果您想知道为什么;更多的是出于好奇,而不是应用程序真正需要它......但我认为最好不要在数据库中使用未使用的列。 附言我不想更改 Django 文件以手动从用户中删除“电子邮件”。

编辑: 后续问题(针对那些想做同样事情的人)Before syncdb, delete field from standard Django model

【问题讨论】:

    标签: django model del


    【解决方案1】:

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

    模型是通过对元类进行一些非常聪明但复杂的修改来构建的。当执行模型类定义时(第一次导入它的 models.py),元类会遍历该模型的所有字段定义,并调用每个字段的 contribute_to_class 方法。这最终将实际字段放入新类的 _meta.fields 属性中。所以模型类本身没有字段作为直接属性。

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

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

    【讨论】:

    • 这很有趣,他们为什么要做这些黑客攻击?
    • 启用漂亮的声明性语法。否则,这些字段实际上将是类属性,因此,如果您在一个实例上设置该值,它将延续到所有实例 - 不是很有用。
    • 小后续问题:如果我在创建 B(A) 类之前从 A() 类中删除一个字段,B 仍然会得到已删除的 A 字段...知道为什么吗?提前致谢!
    • 我不确定这是由于 2011 年以来的变化还是因为它是一个 many2many 字段,但作为对其他人的警告,这在 m2m 字段的 1.8 中不起作用。
    【解决方案2】:

    由于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")
    

    【讨论】:

      猜你喜欢
      • 2012-01-17
      • 2018-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      相关资源
      最近更新 更多