不能使用继承的 Django 模型的 Meta 类来配置在继承的抽象模型中定义的字段

Posted

技术标签:

【中文标题】不能使用继承的 Django 模型的 Meta 类来配置在继承的抽象模型中定义的字段【英文标题】:Can't use an inheriting Django model's Meta class to configure a field defined in an inherited abstract model 【发布时间】:2010-11-24 14:39:02 【问题描述】:

我想使用继承模型的 Meta 类的属性来配置在继承树更高层抽象模型中定义的字段:

class NamedModel(models.Model):
    class Meta:
        abstract = True
        verbose_name = 'object'

    name = models.CharField("Name",
        max_length=200,
        db_index=True,
        help_text="A meaningful name for this %s." % Meta.verbose_name)
        # see what I'm trying to do here?
    )
    ...

class OwnedModel(NamedModel):
    class Meta(NamedModel.Meta):
        verbose_name = 'owned object'

我希望 OwnedModel 表单的名称字段上的帮助文本显示“此拥有对象的有意义名称”。 但事实并非如此:缺少“owned”一词,这表明在设置模型时使用了 NamedModel.Meta 中的 verbose_name,而不是 OwnedModel.Meta。

从继承的角度来看,这并不是我所期望的:是否有某种方法可以创建字段,其中 Meta.verbose_name 指的是非抽象模型类的值,而不是抽象模型类的值定义了哪个字段?

还是我傻了?

(这可能看起来像一个微不足道的例子,但它只是为了说明我正在尝试做的更重要和更复杂的事情)

非常感谢。

【问题讨论】:

【参考方案1】:

你为什么不尝试上课。

class BaseNamedModelMeta:
    abstract = True
    verbose_name = "your text"

然后像这样继承和覆盖你想要的任何东西:

class OwnedModel(NamedModel):
    class Meta(BaseNamedModelMeta):
        verbose_name = 'owned object'

【讨论】:

【参考方案2】:

我认为这是因为使用了 Meta.verbose_name 并在解析 NamedModel 类时创建了 NamedModel.name。所以后来,当 OwnedModel 类被解析时,就没有机会改变任何东西了。

也许您可以稍后在 OwnedModel.name 上设置 help_text 属性,但这也可能会更改 NamedModel.name。

在类似的情况下,我将变量部分放在模型的类属性中(不是 Meta),然后使用运行时方法/属性生成我需要的文本。

【讨论】:

是的,我想就是这样。遵循流程后,我对生命周期更加清晰:在解析类时评估字段,因此不考虑继承。而且我已经尝试过元之外的类属性......当然同样的问题。我很高兴覆盖字段类,我可能会使用它(+您的建议)来获得所需的效果。【参考方案3】:

事实上,我最终做了以下事情。基本模型获得了一个 dynamic_field_definition() 类方法,该方法可用于修补字段,其中 cls 参数是正确的(继承)类。这意味着 cls 的 Meta 属性属于那个正确的孩子,而不是原始的基础。

然后我连接该方法以在 class_prepared 信号上调用,这样您就知道一切都准备好了。

class NamedModel(models.Model):
    ...
    @classmethod
    def dynamic_field_definition(cls):
        pass

def dynamic_field_definition(sender, **kwargs):
    if issubclass(sender, NamedModel):
        sender.dynamic_field_definition()
class_prepared.connect(dynamic_field_definition)

然后,随模型类变化的字段属性只需由该类方法重新配置(或者更可能是在派生类中重写的方法)。

这是为 Django 模型带来最后一点 OO 特性的一种略显老套的方式,但它对我的目的很有效。

【讨论】:

以上是关于不能使用继承的 Django 模型的 Meta 类来配置在继承的抽象模型中定义的字段的主要内容,如果未能解决你的问题,请参考以下文章

python django模型内部类meta

Django模型 ---------Meta

Django模型之Meta详解

Django模型之Meta选项详解

Django模型之Meta选项详解

Django模型之Meta选项详解