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

发布于 2024-08-03 07:34:06 字数 852 浏览 6 评论 0原文

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

还是我很愚蠢?

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

提前非常感谢。

I would like to use properties from an inheriting model's Meta class to configure a field defined in an abstract model higher up the inheritance tree:

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'

I would like the help text on the name field of OwnedModel forms to say 'A meaningful name for this owned object'. But it does not: the word 'owned' is missing, which would suggest that the verbose_name from the NamedModel.Meta is used when the model is set up, not OwnedModel.Meta.

This isn't quite what I expect from an inheritance point of view: is there some way to get the field to be created whereby Meta.verbose_name refers to the value on the non-abstract model class, not the abstract one on which the field was defined?

Or am I being daft?

(This may seem like a trivial example, and it is: but it's just to illustrate the point of something more important and complex I am trying to do)

Many thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

堇年纸鸢 2024-08-10 07:34:06

你为什么不尝试上一堂课呢?

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

然后继承并覆盖你想要的任何内容,如下所示:

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

Why don't you try to make a class.

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

And then inherit and override whatever you want like this:

class OwnedModel(NamedModel):
    class Meta(BaseNamedModelMeta):
        verbose_name = 'owned object'
还在原地等你 2024-08-10 07:34:06

我认为发生这种情况是因为使用了 Meta.verbose_name 并且在解析类 NamedModel 时创建了 NamedModel.name 。因此,稍后,当 OwnedModel 类被解析时,就没有机会更改任何内容。

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

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

I think this happens because Meta.verbose_name is used and NamedModel.name is created when class NamedModel is parsed. So later, when class OwnedModel gets parsed, there is no chance to change anything.

Maybe you can set the help_text property on OwnedModel.name later on, but this may change NamedModel.name also.

In similar situations I have put the variable parts in class attribute of the model (not Meta) and then used the by run time methods/properties to generate the texts I need.

暮年慕年 2024-08-10 07:34:06

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

然后,我连接该方法以在 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 风格的稍微有点老套的方法,但它对于我的目的来说效果很好。

In fact I ended up doing the following. The base model gets given a dynamic_field_definition() class method, which can be used to patch up the fields, with the cls argument being the correct (inheriting) class. That means that that cls' Meta attributes are of that correct child, not the original base.

I then wire up that method to get called on the class_prepared signal, so that you know everything's otherwise ready.

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)

Then the field properties that vary with model class are simply reconfigured by that class method (or more likely the method as overridden in derived classes).

It's a slightly hacky way to bring a last little bit of OO-ness to Django models, but it works fine for my purpose.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文