What is the best way to create a single channel from different models?

On my site I have three models organized in two applications. All these models have a timestamp field that determines the order in which the site feed appears. Instead of creating a feed for each model and making single requests ordered by timestamp field, I want to create a single channel containing all these objects, each of which will have a corresponding template, and all of them are ordered by timestamp .

My first attempt would be to list all the objects and combine them into one list and sort them in 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 
+4
source share
1 answer

I would return an iterator from the items method. in this case, sorting and aggregation of objects can be done in a lazy way. If you pre-sort the three collections of objects that you want to combine before creating an iterator, the final sort is just a matter of choosing the next object from the desired collection at each iteration. Do you understand what I mean?

eg:

 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
+2
source

All Articles