Каков наилучший способ создания одного канала из разных моделей? - PullRequest
4 голосов
/ 03 октября 2011

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

Моей первой попыткой было бы перечислить все объекты и объединить их в один список и отсортировать их в 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 Ответ

2 голосов
/ 03 октября 2011

Я бы вернул итератор из метода 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()<br> try: u = i.next() except StopIteration: u = None<br> try: v = j.next() except StopIteration: v = None<br> 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

...