上下文
我正在使用 Django 模型对我的数据进行建模。
主要模型是一个文章
。它包含实际内容。
然后每个 Article
必须附加到一组文章。这些组可能是Blog
、Category
、Portfolio
或Story
。每一个 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
创建了一个额外的表,然后 Category
和 Blog
有一个指向该表的隐式外键他们的主键。
旁注:我知道有 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 的继承魔法隐含的作用之外,我真的不明白这样做有什么意义。
奖励:多列
它看起来很脏,所以我只是将它添加为奖励,但也可以为每个 Category
、Blog
、.. . 直接在 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/