Каков наилучший способ генерировать один канал из разных моделей?

#django #feed

#django #канал

Вопрос:

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

Моей первой попыткой было бы перечислить все объекты и объединить их в один список и отсортировать их в Python:

 class SiteFeed(Feed):
    ...
    def items(self):
        objects = list(model1.objects.all())   list(model2.objects.all())   list(model3.objects.all())
        objects.sort(key=lamda obj: obj.timestamp)
        return = objects
  

Ответ №1:

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

например:

 class SiteFeed(Feed):
    ...
    def items(self):
        i = model1.objects.order_by('timestamp').iterator()
        j = model2.objects.order_by('timestamp').iterator()
        k = model3.objects.order_by('timestamp').iterator()
        try:                  u = i.next()
        except StopIteration: u = None
        try:                  v = j.next()
        except StopIteration: v = None
        try:                  w = k.next()
        except StopIteration: w = None
        ...
        yield min([u,v,w], key=lambda x: x.timestamp if x else datetime.max)
        ...
        # at this point you need to reiterate the iterator
        # corresponding to the variable that you yielded
        # and yield again
        # so, the above code must be in some sort of a loop
        # until ALL iterators are exhausted
  

Комментарии:

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

2. Это простой итератор. Проблема все еще остается, мне нужны все эти объекты разных моделей, отсортированные по общему атрибуту timestamp . В этом коде возвращаются только model1 объекты.

3. да, я привел вам только пример, поскольку вы сказали, что не привыкли к итераторам. Я снова обновил свой ответ, чтобы дать вам лучшее представление о том, что я имею в виду. Извините, у меня нет времени на написание полного решения. Это псевдокод, я ничего не тестировал.

4. Хорошо, я попробую это и вернусь с комментариями. Спасибо!