如何在Django中建立单向一对一关系的模型

时间:2009-07-13 19:11:55

标签: python django django-models

我想在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)

在artlcle模型上,我希望有2个直接引用修订版 - 一个指向已发布的修订版,另一个指向正在编辑的修订版。但是根据我的理解,OneToOne和ForeignKey引用在模型引用的另一端生成反向引用,所以我的问题是,如何在Django中创建单向一对一引用?

是否有一些特殊的咒语或者我是否必须通过将状态包含在要求在特定状态下进行修订的字段的修订和自定义实现来伪造它?

编辑:我想,我在解释我的意图方面做得不好。让我们在更高的抽象级别上尝试:

我最初的目的是实现一种修改后的文章模型,其中每篇文章可能有多个修订版,其中一个修订版可以“发布”,一个可以被主动编辑。

这意味着该文章与修订版本之间存在一对多的关系(由 ArticleRevision 类中的ForeignKey(Article)引用表示)以及从文章到修订版的两个单向引用: published_revision edited_revision

我的问题主要是,如何使用Django的ORM对此进行建模。

2 个答案:

答案 0 :(得分:4)

链接双向有什么问题?我认为OneToOneField将是这里的完美选择。是否有一个特定的原因会对您的申请造成损害?如果你不需要反向引用,为什么不能忽略它呢?

答案 1 :(得分:4)

Django生成的反向引用是编程的,不会影响底层的数据库模式。换句话说,如果您的文章上有指向修订版的一对一或外键字段,则会在数据库中的Article表中添加一列,但不会将该列添加到Revision表中。

因此,不需要从修订版到文章中删除反向关系。如果你真的对此感到强烈,并希望在你的代码中记录从不使用反向链接,那么一个相当常见的Django习惯用法是给字段一个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上的单个ForeignKey字段指向文章可能是有意义的(因为ArticleRevision可能总是需要与文章关联)并向Revision添加另一列,指示它是否已发布。