7

我想使用继承模型的 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 指的是非抽象模型类上的值,而不是字段所在的抽象类被定义了?

还是我傻?

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

提前谢谢了。

4

3 回答 3

2

你为什么不尝试上课。

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

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

class OwnedModel(NamedModel):
    class Meta(BaseNamedModelMeta):
        verbose_name = 'owned object'
于 2016-05-23T16:10:51.210 回答
1

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

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

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

于 2009-09-01T12:51:15.647 回答
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 特性的一种有点笨拙的方式,但它对我的目的来说很好用。

于 2009-09-01T15:40:27.303 回答