Используя Django, как мне создать серию упорядоченных по дате страниц в стиле Tumblr для различных объектов? - PullRequest
0 голосов
/ 09 января 2012

У меня есть приложение Django с классами для разных вещей, таких как сообщение, цитата, изображение, ссылка и т. Д. Как элементы в Tumblr. Каждый из этих объектов имеет дату и время.

Я хочу отобразить комбинированный список из 20 самых последних элементов всех типов. И я хочу, чтобы иметь возможность просматривать страницы старых предметов. то есть, как страницы Тамблера.

Но я не могу придумать, как выполнять подобные запросы для разных типов объектов ... Должен ли я создать отдельный класс, например:

class CombinedItem(models.Model):
    date = models.DateTimeField()
    item_type = models.CharField() # eg, 'post', 'quote', 'image', 'link'
    item_id = models.IntegerField()

И добавляйте к этому новую запись всякий раз, когда я добавляю новое сообщение, цитату, изображение и т. Д. И затем, для моего списка, запрашиваю класс CombinedItem для самых последних элементов, а затем извлекаю основные сведения для каждого элемента, который он возвращается? Если так, то какой самый эффективный способ сделать все это? Спасибо.

Ответы [ 3 ]

3 голосов
/ 09 января 2012

Лучше всего будет работать наоборот.Каждый из них является типом пользовательского контента, поэтому все они должны наследоваться от общей базы:

class ContentItem(models.model):
    # common fields here

class Post(ContentItem):
    # post specific fields

....

Затем вы можете просто запросить базовую модель ContentItem и получить список всего.

Единственная потенциальная проблема заключается в том, что результатом являются ContentItem с, а не Post с, Quote с и т. Д. Однако в реализации MTI (наследование нескольких таблиц) в Django дочерний классявляется атрибутом родительского класса.Таким образом, «Post» ContentItem будет иметь атрибут .post, из которого вы можете получить доступ к Post.Вы можете комбинировать это с hasattr для создания служебных методов, которые вы можете использовать в своем представлении.Например:

class ContentItem(models.Model):
    ...
    def is_post(self):
        return hasattr(self, 'post')

Затем в вашем шаблоне:

{% if content_item.is_post %}
    <!-- do some post-specific rendering here -->
{% endif %}
1 голос
/ 09 января 2012

Более чистый способ сделать это - создать универсальную модель с именем Item (или CombinedItem, если вы предпочитаете) и создать несколько моделей (Post, Quote, Image и т. Д.), Которые наследуются от нее. Django был разработан с учетом наследования моделей, а ваши конкретные потребности покрываются функцией под названием многостоловое наследование .

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

0 голосов
/ 09 января 2012

Вы можете использовать GenericForeignKey [1], который сгенерирует почти ту же структуру, что и описанную вами.

Самое большое отличие состоит в том, что поле item_type будет фактически внешним ключом в таблице типов содержимого,который Django поддерживает автоматически.

К сожалению, стандартные методы ORM filter () не будут работать в этом поле.Вам нужно будет запросить модели по отдельности для их диапазонов дат.

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

[1] https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#generic-relations

...