Как смоделировать односторонние отношения в Джанго - PullRequest
4 голосов
/ 13 июля 2009

Я хочу смоделировать статью с изменениями в 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?

Существуют ли какие-то особые заклинания для этого или мне нужно подделать его, включив состояние в ревизию и пользовательские реализации полей, которые запрашивают ревизию в определенном состоянии?

Редактировать: Полагаю, я плохо объяснил свои намерения. Давайте попробуем это на более высоком уровне абстракции:

Мое первоначальное намерение состояло в том, чтобы реализовать своего рода пересмотренную модель статьи, в которой каждая статья может иметь несколько ревизий, где одна из этих ревизий может быть «опубликована», а другая - активно редактироваться.

Это означает, что статья будет иметь отношение один-ко-многим к ревизиям (представленным ForeignKey(Article) ссылка в ArticleRevision класс) и две односторонние ссылки из статьи на ревизию: published_revision и edited_revision.

Мой вопрос в основном, как я могу смоделировать это с помощью ORM Джанго.

Ответы [ 2 ]

4 голосов
/ 14 июля 2009

Обратные ссылки, создаваемые Django, являются программными и не влияют на базовую схему базы данных. Другими словами, если в вашей Статье имеется однозначное поле или поле внешнего ключа, указывающее на вашу Редакцию, столбец будет добавлен в таблицу Статьи в базе данных, но не в таблицу Редакций.

Таким образом, удаление обратной связи из редакции к статье не требуется. Если вы действительно сильно к этому относитесь и хотите документировать в своем коде, что обратная ссылка никогда не используется, довольно распространенная идиома Django - присвоить полям атрибут related_name, например _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

Тем не менее, редко когда отношения "один к одному" действительно полезны в приложении (если вы не оптимизируете по какой-то причине), и я бы посоветовал тщательно изучить схему БД, чтобы убедиться, что это действительно то, что вы хочу. Возможно, имеет смысл оставить одно поле ForeignKey в вашем ArticleRevision, указывающее на статью (поскольку ArticleRevision, вероятно, всегда нужно будет связывать со статьей), и добавить в Revision еще один столбец, указывающий, опубликована ли она.

4 голосов
/ 13 июля 2009

Что плохого в том, что ссылка идет в обе стороны? Я думаю, что OneToOneField будет идеальным выбором здесь. Есть ли конкретная причина, по которой это нанесет ущерб вашему приложению? Если вам не нужна обратная ссылка, почему вы не можете просто проигнорировать ее?

...