Django 中的抽象模型和外键
Posted
技术标签:
【中文标题】Django 中的抽象模型和外键【英文标题】:Abstract Models and Foreign Keys in Django 【发布时间】:2011-11-23 20:50:28 【问题描述】:我正在从事一个 django 项目,在该项目中我创建了一组三个抽象模型,稍后我将在各种应用程序中使用它们。我遇到的问题是我想通过 ForeignKey 连接这些模型,但 django 告诉我它不能将外键分配给抽象模型。
我当前的解决方案是在我的其他应用程序中实例化类时分配外键。但是,我现在正在为抽象类(书籍和页面)编写一个管理器,并且需要访问这些外键。我基本上想做的是以无状态的方式获取一本书的字数,因此无需将其存储在页面或书籍的字段中。
模型看起来类似于这样:
class Book(models.Models):
name = models.CharField(...)
author = models.CharField(...)
...
class Meta:
abstract = True
class Page(models.Models):
book = models.ForeignKey(Book)
chapter = models.CharField(...)
...
class Meta:
abstract = True
class Word(models.Models):
page = models.ForeignKey(Page)
line = models.IntegerField(...)
...
class Meta:
abstract = True
请注意,这里的这个模型只是为了举例说明我正在尝试做的事情,因此不需要这个模型(Book-Page-Word)从实现的角度来看是否有意义。
【问题讨论】:
【参考方案1】:也许您在这里需要的是GenericForeignKey
,因为您实际上并不知道您的ForeignKey
s 将指向什么型号?这意味着您将失去一些正常关系的“类型安全”保证,但它允许您以更一般的方式指定这些关系。见https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericForeignKey
Django 模型继承是一件很酷的事情,并且可以作为使模型 DRYer 的捷径,但并不总是与我们通常对类的多态想法很好地配合。
【讨论】:
【参考方案2】:这种方法怎么样?我正在考虑自己使用它来延迟关系定义,直到我继承。
# 这是一个非常做作(但很简单)的例子。
def AbstractBook(AuthorModel):
class AbstractBookClass(Model):
name = CharField(max_length=10)
author = ForeignKey(AuthorModel)
class Meta:
abstract = True
return AbstractBookClass
class AbstractAuthor(Model):
name = CharField(max_length=10)
class Meta:
abstract = True
class BadAuthor(AbstractAuthor):
pass
class BadBook(AbstractBook(BadAuthor)):
pass
class GoodAuthor(AbstractAuthor):
pass
class GoodBook(AbstractBook(GoodAuthor)):
pass
【讨论】:
读到这让我很受伤【参考方案3】:两件事:
1) 如前所述,按照您构建架构的方式,您将需要一个 GenericForeignKey。但是您必须考虑到 Book through Page 与 Word 具有 多对多 关系,而 GenericForeignKey 只是实现 一对多。对于规范化模式,Django 没有任何开箱即用的东西。您将要做的(如果您关心规范化)是自己实现中间体(对于具体模型使用“通过”)。
2) 如果您关心语言处理,考虑到生成的数据库大小和几十本书后的查询时间,使用关系数据库(有或没有 Django 的 ORM)不是一种非常有效的方法。此外,由于抽象模型,您需要查找连接的额外列,它很快就会变得非常不切实际。我认为根据您的查询和视图研究其他方法会更有益,例如仅存储聚合和/或非规范化(在这种情况下甚至研究非关系存储系统)。
【讨论】:
以上是关于Django 中的抽象模型和外键的主要内容,如果未能解决你的问题,请参考以下文章