Джанго моделирует общее моделирование - PullRequest
2 голосов
/ 21 декабря 2009

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

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

class Page(models.Model):
    name = models.CharField(max_length=64)

class Block(models.Model):
    page = models.ForeignKey(Page)

    class Meta():
        abstract = True

class BlockType1(Block):

    other_data = models.CharField(max_length=32)

    def render(self):
        """Some "stuff" here """
        pass

class BlockType2(Block):

    other_data2 = models.CharField(max_length=32)

    def render(self):
        """Some "other stuff" here """
        pass

Но тогда,

  • Даже с этим кодом я не могу выполнить запрос типа page.block_set.all(), чтобы получить все различные блоки, независимо от типа блока.
  • Причина вышеизложенного состоит в том, что каждая модель определяет свою таблицу; Решение этой проблемы с помощью модели связывания и универсальных внешних ключей может решить проблему, но при этом все еще оставляет запросы к нескольким таблицам базы данных на страницу.

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

Обновление:

Моя точка зрения была такой: Как я могу все еще заставить работать парадигмы ООП . Использование одного и того же метода с так много ifs не то, что я хотел сделать.

Лучшее решение, как мне кажется, состоит в создании отдельного стандартного класса Python (предпочтительно в другом blocks.py), который определяет сохранение, которое сохраняет данные и их «тип» путем создания экземпляров той же модели. Затем создайте тег шаблона и фильтр, который вызывает методы рендеринга, сохранения и другие, в зависимости от типа модели.

Ответы [ 2 ]

4 голосов
/ 21 декабря 2009

Не моделируйте страницу в базе данных. Страницы - это презентация.

Во-первых - и прежде всего - получить правильные данные.

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

Серьезно. Просто определите данные в модели без какого-либо рассмотрения представления или воспроизведения или чего-либо еще. Получите модель данных правильно.

Если вы перепутаете модель и презентацию, вы никогда не получите ничего, чтобы работать хорошо. И если вы заставите его работать, вы никогда не сможете его расширить или использовать повторно.

Секунда - только после того, как модель данных вправо - вы можете перейти к представлению.

Ваши «блоки» можно сделать просто с помощью тегов HTML <div> и таблицы стилей. Попробуйте сначала. Ведь модель работает и очень проста. Это просто HTML и CSS, отдельно от модели.

Вашим "блокам" могут потребоваться пользовательские теги шаблона для создания более сложного, условного HTML. Попробуйте эту секунду.

Ваши "блоки" могут - в крайнем случае - быть настолько сложными, что вам придется написать специальную функцию представления для преобразования нескольких объектов в HTML. Это очень, очень редко. Вам не следует делать это, пока вы не уверены, что не можете сделать это с тегами шаблона.


Редактировать.

"запрос различных внешних источников данных"

"отдельные простые классы (не модели), имеющие метод сохранения, которые записывают в одну и ту же таблицу базы данных."

У вас есть три совершенно разные, не связанные, разные вещи.

  • Модель. Постоянная модель. С помощью метода save(). Это очень, очень мало. У них есть атрибуты и несколько методов. Нет «запроса различных внешних источников данных». Нет «рендеринга в HTML».

  • Внешние источники данных. Это обычные классы Python, которые получают данные. Эти объекты (1) получают внешние данные и (2) создают объекты Model. И ничего больше. Нет "настойчивости". Нет «рендеринга в HTML».

  • Презентация. Это обычные шаблоны Django, которые представляют объекты Model. Нет внешнего запроса. Нет настойчивости.

1 голос
/ 21 декабря 2009

Я только что закончил создание прототипа системы, которая имеет эту проблему в пики: базовый класс Product и около 200 классов детализации, которые сильно различаются. Во многих ситуациях мы делаем общие запросы к Product, но затем хотим иметь дело с деталями, относящимися к подклассу, во время рендеринга. Например. получить все продукты от поставщика X, но отобразить с немного отличающимися шаблонами для каждой группы из определенного подкласса.

Я добавил скрытые поля для GenericForeignKey в базовый класс, и он автоматически заполняет content_type & object_id дочернего класса во время save (). Когда у нас есть универсальный объект Product, мы можем сказать obj = prod.detail и затем работать напрямую с объектом подкласса. Взял около 20 строк кода, и он прекрасно работает.

Единственное, с чем мы столкнулись во время тестирования, было то, что manage.py dumpdata, а затем manage.py loaddata продолжали бросать Integrity Errors. Оказывается, это хорошо известная проблема, и ожидается исправление в выпуске 1.2. Мы обходим это, используя команды mysql для выгрузки / перезагрузки тестового набора данных.

...