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

时间:2009-09-01 10:55:44

标签: python django inheritance django-models metaclass

我想使用继承模型的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表单名称字段上的帮助文本说“这个拥有对象的有意义的名称”。 但它没有:缺少“拥有”这个词,这表明在建立模型时使用NamedModel.Meta中的verbose_name,而不是OwnedModel.Meta。

这不是我对继承观点的期望:是否有某种方法可以创建字段,其中Meta.verbose_name引用非抽象模型类上的值,而不是抽象模型类上的值哪个领域被定义了?

还是我愚蠢?

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

非常感谢提前。

3 个答案:

答案 0 :(得分:2)

你为什么不尝试上课。

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

然后继承并覆盖你想要的任何东西:

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

事实上我最终做了以下事情。给基本模型一个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-ness引入Django模型是一种稍微晦涩的方式,但它适用于我的目的。