Django:使用ContentType与multi_table_inheritance

Z. *_*Lin 8 django django-models

我遇到了类似于 如何在Django中查询基于抽象类的对象的问题? 该线程建议使用multi_table_inheritance.我个人认为使用content_type在概念上更舒服(感觉更接近逻辑,至少对我而言)

使用上一个链接中的示例,我只需添加一个StelarType

class StellarType(models.Model):
    """
    Use ContentType so we have a single access to all types
    """
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
Run Code Online (Sandbox Code Playgroud)

然后将其添加到抽象基础模型中

class StellarObject(BaseModel):
    title = models.CharField(max_length=255)
    description = models.TextField()
    slug = models.SlugField(blank=True, null=True)
    stellartype = generic.GenericForeignKey(StellarType)
    class Meta:
        abstract = True
Run Code Online (Sandbox Code Playgroud)

要在StellarObject和StellarType之间进行同步,我们可以连接post_save信号,以便在每次创建Planet或Star时创建StellarType实例.通过这种方式,我可以通过StellarType查询StellarObjects.所以我想知道使用这种方法反对使用multi_table_inheritance的PRO和CON是什么?我认为两者都在数据库中创建了一个额外的表.但是数据库性能呢?可用性/灵活性如何?感谢您的任何投入!

acj*_*jay 5

对我来说,当你想要将一个对象与一个基本上不是同一"类型"的模型之一联系起来时,ContentType就是你的选择.就像您希望能够在社交网络上对用户,页面和图片进行关键评论一样,但这三个模型没有共享的合理超类型.当然你可以创建一个"可评论的"超类型,但对我来说,感觉更像是一个混合而不是这三个东西衍生出来的基本类型.ContentType的出来之前,你将不得不无奈地发明了超类型,这些类型的关系,如果你需要多次做在同一个应用程序,它可以得到真正的丑陋真的很快(可以说你也有事件,警报消息等,每个消息可以应用于不同的模型集).

当您想要将属性附加到基础模型时,多表继承最有意义,这样它们将在从其扩展的所有具体模型中共享,以便您可以获得多态行为.Commentable并不适合这种模式,因为所有这些行为都可以放在Comment模型上,而不是评论对象.但是,如果您有不同类别的用户,他们共享大部分相同的行为并且应该是可聚合的,那么它会更有意义.

多表继承我的主要职业是一个更干净的数据模型中,可以在Python端被利用(多态性仍是有点乱,虽然,所看到的隐含关系和继承在这里这里).则contentType的主要职业是,它是更普遍的,并保持辅助功能,你的模型,在一个有点略显不足原始架构的成本(很多您的模型"元"字段来定义这些关系).而对于你的例子,你仍然需要依赖post_save,这对我来说似乎也是不必要的混乱/魔法.

  • 我喜欢*两个Scoops,但对多表继承的毯子告诫我真的不明白.您只需要了解将为您的应用程序生成的查询以及它们是否代表问题.如果你可以在超类型表上完成大部分工作,那么它尤其没有问题.从性能的角度来看,我无法想到为什么查询超类型表并加入子类型应该比对通用ContentType表执行相同更糟糕.我可以看到你为什么要避免一个非常复杂的类型层次结构... (2认同)