Модель наследования и администрирования Django - PullRequest
6 голосов
/ 21 марта 2011

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

В моем коде моделирования у меня есть базовый класс:

class ContentItem(models.Model):
    title = models.CharField(max_length=1000)
    page_order = models.IntegerField()
    last_update_date = models.DateTimeField(default=datetime.now())

    class Meta:
      abstract = True
      ordering = ['page_order', 'last_update_date', 'title']

Это базовый класс для всех элементов контента.Порядок страниц определяет, какая позиция на странице, например, элемент с page_order = 0 должен быть в верхней части страницы.Далее я определяю несколько конкретных моделей контента, которые наследуются от этой.

class LinkContent(ContentItem):
  url = models.URLField()
  link_text = models.CharField(max_lenth=1000)

class TextContent(ContentItem):
 text = models.CharField()


class VideoContent(ContentItem):
      title = models.CharField()
      video_file = models.FieldField(upload_to = 'videos')

Таких типов контента может быть еще много.Затем я бы определил модель страницы, которая состоит из всех различных типов контента.В идеале я мог бы поместить все типы в отношения на основе базового типа.Таким образом, в этом одном отношении у вас будет смесь LinkContents, TextContents и VideoContents.Они будут отсортированы по page_order для определения их порядка на странице при отображении шаблона.

class Page(models.Model):
  contents = models.ManyToManyField(ContentItem)
  title = models.CharField()

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

Нужно ли мне что-то более похожее на это:

class Page(models.Model):
  video_contents = models.ManyToManyField(VideoContent)
  link_contents = models.ManyToManyField(LinkContent)
  text_contents = models.ManyToManyField(TextContent)
  title = models.CharField()

Я знаю, что это сработает, но моя схема определения размещения объектов на странице становится более сложной.Мне нужно будет пройти через все контентные отношения, отсортировать их по page_order и затем отобразить их.

Я думаю, что в обоих случаях я хочу объявить метод render () в базовом классе, который может наследовать каждый конкретный тип контента.Таким образом, если у меня есть список ContentItems, я могу использовать утку, чтобы визуализировать их, не беспокоясь об их конкретном типе.

Мой последний вопрос: как сделать так, чтобы администратор с этим справлялся?Как бы я сделал простой способ увидеть все ContentItems, которые составляют страницу, в одном представлении, чтобы их можно было легко перемещать, изменяя page_order?

Спасибо за прочтение, дайте мне знать, если вынужна дополнительная информация.

1 Ответ

3 голосов
/ 21 марта 2011

Это прекрасный способ сделать это.К сожалению, ORM Django не обрабатывает наследование моделей так гладко, как вы этого хотите.page.contents будет содержать QuerySet из Content объектов.Если вы хотите получить доступ к подтипам, вам нужно создать какой-то способ понижения содержания объекта.Проблема в том, что для этого требуется запрос на объект, который может быстро выйти из-под контроля. В этом блоге описывается методика получения смешанных подтипов в одном наборе запросов с использованием select_related() за кулисами.

...