Django:使用ContentType与多表继承

Django:使用ContentType与多表继承,django,django-models,Django,Django Models,我的问题和我的一样 线程建议使用多表继承。我个人认为使用内容类型在概念上更舒适(只是感觉更接近逻辑,至少对我来说) 使用前面链接中的示例,我只想添加一个StelarType作为 class StellarType(models.Model): """ Use ContentType so we have a single access to all types """ content_type = models.ForeignKey(ContentType)

我的问题和我的一样 线程建议使用多表继承。我个人认为使用内容类型在概念上更舒适(只是感觉更接近逻辑,至少对我来说)

使用前面链接中的示例,我只想添加一个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')
然后将其添加到抽象基础模型中

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
为了在StellarObject和StellarType之间进行同步,我们可以在每次创建行星或恒星时连接post_save信号来创建StellarType实例。通过这种方式,我可以通过StellarType查询StellarObject。
所以我想知道使用这种方法与使用multi_table_继承相比有什么利弊?我认为两者都会在数据库中创建一个额外的表。但是数据库性能如何呢?可用性/灵活性如何?谢谢你的任何意见

对我来说,当你想将一个对象与许多基本上不属于同一“类型”的模型中的一个相关联时,ContentType就是一种方法。比如,如果你想在社交网络上为用户、页面和图片添加关键评论,但这三种模式没有合理的共享超类型。当然,您可以创建一个“可注释”超类型,但对我来说,这更像是一个混合类型,而不是从中派生出这三种类型的基本类型。在ContentType问世之前,你别无选择,只能为这种关系发明超类型,如果你需要在同一个应用程序中多次这样做,那么这种关系很快就会变得非常丑陋(假设你还有事件、警报、消息等,每种都可以应用于不同的模型集)

当您希望将属性附加到基础模型时,多表继承最有意义,这样它们将在从基础模型扩展而来的所有具体模型中共享,从而可以获得多态行为。Commentable并不真正符合这种模式,因为所有这些行为都可以放在Comment模型上,而不是放在Commentable对象上。但是如果你有不同类别的用户,他们有着相同的行为,并且应该受到攻击,那么这就更有意义了


对我来说,多表继承的主要优点是更干净的数据模型,在Python端可以利用隐式关系和继承(多态性仍然有点混乱,如图和所示)。ContentType的主要优点是,它更通用,并将辅助功能排除在模型之外,但代价是稍微少了一点原始模式(模型上有许多“元”字段来定义这些关系)。举个例子,您仍然必须依赖于
post_save
,这对我来说似乎是不必要的混乱/神奇。

很抱歉恢复了旧线程。我认为这一切归结为查找方向。无论是查找某个FK(多任务继承)的所有子类,还是将引用的类定义为内容类型并基于表引用和id(contenttypes)进行查找,在性能上都没有太大的区别-提示:它们都很糟糕。我认为,如果你希望你的应用程序易于扩展,那么内容类型是一个不错的选择,也就是说,其他人可以添加新的内容类型作为参考。如果您只是偶尔需要在额外的表中定义额外的列,那么Multitable是很好的。有时,合并所有子类型并只使其中一个字段大部分时间为空也可能是一个好主意。

对于将ContentTypes框架用于不相关的内容,我也有同样的感觉,但我觉得使用多表继承有点不舒服。为了在最佳实践世界中得到指导,我在Pydenny的书(2勺)中读到多桌是邪恶的。最后一个问题是:效率还是优雅?我喜欢两个勺子,但对多表继承的全面警告我真的不明白。您只需要了解将为应用程序生成的查询,以及它们是否表示问题。如果您可以在超类型表上完成大部分工作,那么它尤其没有问题。从性能的角度来看,我想不出为什么查询超类型表并连接到子类型比查询泛型ContentType表更糟糕。我可以理解为什么你想要避免一个非常复杂的类型层次结构…我同意你的看法。我正在寻找一种很好的方法来处理这个问题,我刚刚发现这个应用程序(django model utils)似乎非常有用:是的!我以前使用过它,它大大减少了在多表继承中争论子类的痛苦。