如何在Django中建模单向一对一关系
我想在Django中建模一个有版本的文章:
在我的文章模型的models.py文件中,我有以下内容:
class Article(models.Model):
title = models.CharField(blank=False, max_length=80)
slug = models.SlugField(max_length=80)
def __unicode__(self):
return self.title
class ArticleRevision(models.Model):
article = models.ForeignKey(Article)
revision_nr = models.PositiveSmallIntegerField(blank=True, null=True)
body = models.TextField(blank=False)
在文章模型中,我想有两个直接指向版本的引用,一个指向已发布的版本,另一个指向正在编辑的版本。不过根据我的理解,OneToOne和ForeignKey引用会在模型的另一侧生成一个反向引用,所以我想问的是,如何在Django中创建一个单向的一对一引用?
这有什么特别的方法吗?还是说我需要通过在版本中加入状态,以及自定义实现那些需要特定状态版本的字段来“伪造”这个引用?
编辑:我想我之前没有很好地解释我的意图。让我们试着从更高的抽象层次来看看:
我最初的想法是实现一个有版本的文章模型,每篇文章可以有多个版本,其中一个版本可能是“已发布”的,另一个是正在编辑的。
这意味着文章和版本之间是一个多对一的关系(在ArticleRevision类中用ForeignKey(Article)
表示),同时从文章到版本有两个单向引用:published_revision
和edited_revision
。
我主要想问的是,如何用Django的ORM来建模这个关系。
2 个回答
这个双向链接有什么问题呢?我觉得使用OneToOneField
应该是个不错的选择。有没有什么特别的原因会对你的应用造成不利影响?如果你不需要反向引用,那为什么不直接忽略它呢?
Django生成的反向引用是程序内部的东西,不会影响数据库的基本结构。换句话说,如果你的文章(Article)有一个一对一或外键字段指向修订(Revision),那么在数据库的文章表中会增加一列,但修订表不会增加任何列。
因此,从修订到文章的反向关系是可以不去管的。如果你真的觉得有必要说明这个反向链接没有被使用,可以在代码中给这些字段加个related_name属性,比如 _unused_1
。这样你的文章模型可能看起来像下面这样:
class Article(models.Model):
title = models.CharField(blank=False, max_length=80)
slug = models.SlugField(max_length=80)
revision_1 = models.OneToOneField(ArticleRevision, related_name='_unused_1')
revision_2 = models.OneToOneField(ArticleRevision, related_name='_unused_2')
def __unicode__(self):
return self.title
不过,实际上在应用中一对一的关系很少有用(除非你有特别的优化需求),我建议你仔细检查一下你的数据库结构,确保这真的是你想要的。可能更合理的是在文章修订(ArticleRevision)中保留一个指向文章的外键字段(因为修订通常需要和某篇文章关联),并在修订中增加另一列来表示它是否已发布。