首页 文章

可以't use an inheriting Django model'的Meta类来配置继承的抽象模型中定义的字段

提问于
浏览
6

我想使用继承模型的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表单的名称字段上的帮助文本说'A meaningful name for this owned object' . But it does not :缺少单词'owned',这表示在 Build 模型时使用NamedModel.Meta中的verbose_name,而不是OwnedModel.Meta .

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

还是我愚蠢?

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

提前谢谢了 .

3 回答

  • 1

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

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

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

  • 1

    你为什么不试着上课?

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

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

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

    事实上,我最终做了以下事情 . 给基本模型一个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带到一个稍微有点hacky的方式,但它适用于我的目的 .

相关问题