【问题标题】:How to model one way one-to-one relationship in Django如何在 Django 中建模一种方式的一对一关系
【发布时间】:2009-07-13 19:11:54
【问题描述】:

我想在 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) 引用表示)和从文章到修订的两个单向引用:@ 987654325@edited_revision.

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

【问题讨论】:

  • 不是一个真正的答案,但已经有几个用于版本控制 Django 模型的解决方案,例如django-reversion (code.google.com/p/django-reversion) 或 AuditTrail (code.djangoproject.com/wiki/AuditTrail)。也许其中之一适合您的需求,您不必重新发明轮子:-)
  • 我不想对我的模型进行自动版本控制(这就是这两个所做的)。我正在寻找更多的是“手动”修订,其中文章修订一篇文章,直到它被发布。对已发表文章的任何编辑都会创建一个新修订。发布新修订版将锁定此修订版并将其设置为已发布修订版,并且文章的下一次编辑将重新重复编辑-发布周期(我个人认为,对于普通用户来说,这比“每次编辑都是修订版”更易于管理" 方法)。

标签: python django django-models


【解决方案1】:

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

因此,没有必要从修订中删除与文章的反向关系。如果你真的对此有强烈的感觉,并且想在你的代码中记录从不使用反向链接,一个相当常见的 Django 习惯用法是给字段一个相关的名称属性,如_unused_1。因此,您的 Article 模型可能如下所示:

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 添加另一列以指示它是否已发布,这可能是有意义的。

【讨论】:

  • 一对一的关系确实很有用,但在我的情况下,反向引用应该已经以文章修订引用的形式存在,并且附加引用只是为了标记对当前的直接引用已发布的修订版和当前编辑的修订版。
  • 从 Django 1.2 开始,related_name='+' 将导致没有后向关系可用。 docs.djangoproject.com/en/1.2/ref/models/fields/…
【解决方案2】:

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

【讨论】:

  • 如果您需要指向两个不同的 ArticleRevision 模型,related_name 参数将解决表的任何问题。这就是我的答案。
猜你喜欢
  • 2016-11-30
  • 1970-01-01
  • 2022-11-14
  • 1970-01-01
  • 2016-08-15
  • 2023-03-31
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多