9

我遇到了与 如何在 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')

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

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 信号以在每次创建 Planet 或 Star 时创建一个 StellarType 实例。这样,我就可以通过 StellarType 查询 StellarObjects。所以我想知道使用这种方法反对使用 multi_table_inheritance 的优点和缺点是什么?我认为两者都在数据库中创建了一个附加表。但是数据库性能如何?可用性/灵活性如何?感谢您的任何意见!

4

2 回答 2

6

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

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

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

于 2012-10-19T08:40:49.833 回答
0

抱歉恢复旧线程。我认为这一切都归结为查找方向。无论您是查找某个 FK(多表继承)的所有子类,还是将引用的类定义为内容类型并根据表引用和 id(内容类型)进行查找,性能都没有太大差异 - 提示:它们都很糟糕。如果您希望您的应用程序易于扩展,我认为内容类型是一个不错的选择,即其他人可以添加新的内容类型以供参考。如果您有时只需要在额外表中定义的额外列,多表是很好的。有时,合并所有子类型并只制作一个在大多数情况下有几个字段留空的子类型也是一个好主意。

于 2015-12-24T00:32:51.777 回答