Моделирование сложных отношений в Джанго - PullRequest
3 голосов
/ 27 июня 2009

Я работаю над веб-сервисом в Джанго, и мне нужно смоделировать очень специфические, сложные отношения, которые я просто не могу решить.

Представьте себе три общие модели, назовем их Site, Category и Item. Каждый сайт содержит одну или несколько категорий, но он может относиться к ним одним из двух возможных способов: одна - это «общие» категории, которые имеют отношение «многие ко многим»: они предопределены, и каждый сайт может относиться к нулю или больше категорий, и наоборот. Другие типы категорий индивидуально определены для каждого сайта, и одна такая категория «принадлежит» только этому сайту и никому другому; то есть они находятся в отношениях «многие-к-одному», поскольку у каждого сайта может быть несколько таких категорий.

Внутренне эти два типа категорий полностью идентичны, они отличаются только тем, как они связаны с сайтами. Однако он мог бы разделить их на две разные модели (возможно, с общей родительской моделью), но это решает только половину моей проблемы: модель «Предмет» находится в отношении «многие к одному» с категориями, то есть каждый элемент принадлежит только одна категория, и в идеале должно быть все равно, как она связана с сайтом.

Другим решением было бы позволить сосуществовать двум отдельным типам отношений Site-Category (т. Е. Иметь поля ForeignKey и ManyToMany в одной и той же модели категории), но это решение похоже на открытие совершенно другой банки червей. .

У кого-нибудь есть идея, есть ли третье, лучшее решение для этого тупика?

Ответы [ 3 ]

4 голосов
/ 27 июня 2009

Почему бы не иметь оба типа категорий в одной модели, чтобы у вас было только 3 модели?

Site

Category
  Sites = models.ManyToManyField(Site)
  IsCommon =   models.BooleanField()

Item
  Category = models.ForeignKey(Category)

Вы говорите: «Внутри эти два типа категорий полностью идентичны». Так что в таких звуках это возможно. Обратите внимание, что для ManyToManyField вполне допустимо иметь только одно значение, поэтому вам не нужно указывать «ForeignKey и поле ManyToMany в одной и той же модели категорий», что звучит просто как хлопот. Просто введите только одно значение в поле ManyToMany

1 голос
/ 30 июня 2009

В качестве альтернативной реализации вы можете использовать типы контента django (общие отношения), чтобы выполнить соединение элементов. Преимуществом использования этой реализации является то, что она позволяет вам использовать модели категорий по-разному в зависимости от ваших потребностей в данных в будущем.

Вы можете упростить использование категорий сайтов, написав модельные методы для извлечения и сортировки категорий. Контент-администратор Django также поддерживает встроенные родовые отношения.

Ваши модели будут выглядеть следующим образом:

Site(models.Model):
  label = models.CharField(max_length=255)

Category(models.Model):
  site = models.ManyToManyField(Site)
  label = models.CharField(max_length=255)

SiteCategory(models.Model):
  site = models.ForeignKey(Site)
  label = models.CharField(max_length=255)

Item(models.Model):
  label = models.CharField(max_length=255)
  content_type = models.ForeignKey(ContentType)
  object_id = models.PositiveIntegerField()
  content_object = generic.GenericForeignKey('content_type', 'object_id')

Более подробный обзор типов контента и способов запроса родовых отношений вы можете прочитать здесь: http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/

0 голосов
/ 28 июня 2009

Предостережение: я знаю отображение Object-Relation, Rails и Python, но конкретно не Django.

Я вижу два дополнительных варианта:

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

Если вы работаете с более ранней версией Django, вы все равно можете сделать это, превратив модель «многие таблицы» в явную модель.

  1. Думая с точки зрения объекта, я видел разделение категорий на три класса:

    BaseCategory

    CommonCategory (BaseCategory)

    SiteCategory (BaseCategory)

и затем используйте одну из моделей наследования Django.

...