django - 使用 GenericForeignKey 与多表继承与 OneToOneField 的优缺点是什么?

标签 django database

上下文

我正在使用 Django 模型对我的数据进行建模。 主要模型是一个文章。它包含实际内容。

然后每个 Article 必须附加到一组文章。这些组可能是BlogCategoryPortfolioStory。每一个 Article 都必须附加到一个,并且恰好是其中一个。即,博客、类别或故事。这些模型具有非常不同的领域和特征。

我想到了三种方法来实现该目标(还有一个看起来确实不对劲的额外方法)。

选项 #1:通用外键

django.contrib.contenttypes.fields.GenericForeignKey。它看起来像这样:

class Category(Model):
    # some fields

class Blog(Model):
    # some fields

class Article(Model):
    group_type = ForeignKey(ContentType)
    group_id = PositiveIntegerField()
    group = GenericForeignKey('group_type', 'group_id')
    # some fields

在数据库方面,这意味着模型之间实际上不存在任何关系,它们由 Django 强制执行。

选项 #2:多表继承

使文章组全部继承自 ArticleGroup 模型。这看起来像这样:

class ArticleGroup(Model):
    group_type = ForeignKey(ContentType)

class Category(ArticleGroup):
    # some fields

class Blog(ArticleGroup):
    # some fields

class Article(Model):
    group = ForeignKey(ArticleGroup)
    # some fields

在数据库端,这为 ArticleGroup 创建了一个额外的表,然后 CategoryBlog 有一个指向该表的隐式外键他们的主键。

旁注:我知道有 a package自动记录此类结构。

选项 #3:手动 OneToOneFields

在数据库方面,它等同于选项#2。但是在代码中,所有的关系都是明确的:

class ArticleGroup(Model):
    group_type = ForeignKey(ContentType)

class Category(Model):
    id = OneToOneField(ArticleGroup, primary_key=True)
    # some fields

class Blog(Model):
    id = OneToOneField(ArticleGroup, primary_key=True)
    # some fields

class Article(Model):
    group = ForeignKey(ArticleGroup)
    # some fields

除了明确说明 Django 的继承魔法隐含的作用之外,我真的不明白这样做有什么意义。

奖励:多列

它看起来很脏,所以我只是将它添加为奖励,但也可以为每个 CategoryBlog、.. . 直接在 Article 模型上。

所以...

...我真的无法在这些之间做出决定。每种方法的优缺点是什么?有一些最佳实践吗?我错过了更好的方法吗?

如果这很重要,我使用的是 Django 1.8。

最佳答案

似乎没有人可以就此提出建议。 我最终选择了多列选项,尽管我说过它看起来很丑。这一切都归结为 3 件事:

  • 基于数据库的可执行性。
  • Django ORM 使用不同结构的方式。
  • 我自己的需求(即对组进行集合查询得到元素列表,对元素单独查询得到组)。

选项#1

  • 无法在数据库级别强制执行。
  • 在查询时可能很高效,因为它的构造方式不会落入通常的通用外键陷阱。当项目是通用的而不是集合时,就会发生这种情况。
  • 但是,由于 ORM 处理 GFK 的方式,无法使用我需要的自定义管理器,因为我的文章是使用 django-hvad 翻译的.

选项 #2

  • 可以在数据库级别实现。
  • 可能有点高效,但会遇到 ORM 限制,这显然不是围绕此用途构建的。除非我经常使用 extra() 或自定义查询,但在某些时候没有理由再使用 ORM。

选项 #3

  • 实际上会比 #2 好一点,因为将事情明确化可以在使用 ORM 时更轻松地进行查询优化。

多列

  • 结果并没有那么糟糕。它可以在数据库级别强制执行(FK 约束加上手动 CHECK 以确保只有一个列是非空的)。
  • 简单高效。一个直观的查询就可以完成这项工作:select_related('category', 'blog', ...)
  • 虽然它确实存在难以扩展的问题(任何新类型也需要更改 Article 的表)并限制可能的类型数量,但我不太可能运行进入那些。

希望它能帮助任何有同样困境但仍然有兴趣听取其他意见的人。

关于django - 使用 GenericForeignKey 与多表继承与 OneToOneField 的优缺点是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30562039/

相关文章:

Django:id 字段的值即将到来 None

python - 如何解析 django 模板并渲染特定标签

python - 返回时Django聚合字段错误

asp.net - 最佳实践 ASP.NET 成员资格 : User tables in the same datastore?

php - 如何将多列输出作为一列并找到该列的顶部

python - 是否有积极开发的 Django/Python 工作流框架?

python - django 表单 "unexpected keyword argument ' 查询集'"

database - 在 for 循环中使用 db 连接时内存泄漏

java - 部分记录未插入数据库表中

c - 自动启动程序不像手动启动那样工作