1

I have an app that I want to build a "recent activity"/firehose feed of 2-3 combined types of activity such as posts, comments, and likes of posts, and something else + maybe more later. I assume this is done with a query of taking the last of the appropriate object added to the DB and combining it with the last of the other type of object and ordering the new combined list of objects by their timestamps. What is the best way to do something like this? For now, I have something like this for every time someone refreshes the page:

NewPost.objects.all().order_by('-postdate')[0:10] #takes the last 16 recently added posts
Comment.objects.all().order_by('-commentdate')[0:10] #takes equal number of comments site wide ordered by timestamp

So what is the best way to take both of these querysets and render the different Models in 1 list ordered by their timestamp? I assume the type of logic will be the same for adding additional types of objects, so I just want to know how to do it with just 2. Thanks!

EazyC
  • 809
  • 1
  • 10
  • 30
  • possible duplicate of [How to combine 2 or more querysets in a Django view?](http://stackoverflow.com/questions/431628/how-to-combine-2-or-more-querysets-in-a-django-view) – Marius Jul 13 '15 at 06:15
  • I once used [django-activity-stream](https://github.com/justquick/django-activity-stream) for this purpose – jgadelange Jul 13 '15 at 06:22

2 Answers2

1

To combine the lists, you can use create a list by using chain() from itertools, and then sort them by using sorted():

from itertools import chain
combined_lists = list(chain(new_post_list, comment_list))
sorted_combinened_list = sorted(combined_list, key=lambda instance: instance.postdate)

However, as you see, the sorting is only done by using one key. I don't know of any method to use two different keys when sorting. You could fix this by simply add a property to the Comment class, named postdate that simply returns commentdate. Or, even better, you should use the same name for creation time for all your models, e.g. created_at.

This has been answered earlier and more detailed here: How to combine 2 or more querysets in a Django view?

Community
  • 1
  • 1
Christoffer Karlsson
  • 4,539
  • 3
  • 23
  • 36
  • Thank you for the detailed response. I might just go through and rename all of my models to created_at properties for the DateTimeField and migrate the changes, but I will try the suggestion given by Serafeim as well to see which one is a better fix. – EazyC Jul 13 '15 at 09:38
1

I don't really like your approach since when you want to put another object on the firehose you'd need to add a third line (AnotherObject.objects.all ... etc ) to all places you need to display that firehose !

For me, the best way to do this is to create a Firehose Model with fields like: date, action (add/delete/update etc) and object (a generic Foreign Key to the object that was changed). Now, whenever you make a change to an object that you want to add to the firehose, you'd add a new instance of the FirehoseClass with the correct field values. Finally, whenever you want to display the firehose you'll just display all firehose objects.

Serafeim
  • 14,962
  • 14
  • 91
  • 133
  • I think I understand what you are recommending, if it's not too much trouble, can you give me a very basic example rundown of how this Firehose model would work with 2 simple models, a Post model and a Comment model that need to be in the firehouse? I really appreciate it. I think the action property is what is confusing me a bit in your explanation. – EazyC Jul 13 '15 at 09:39
  • The action field is not really required, it's just a description of what each action on the firehose means (something similar like what django admin does when listing your recent actions). What it means is that if you add a new object (that is observed in yourt firehose) then you'll add a new firehose object with action "add" and an FK to that object. You may safely ommit the action of course. I home I made myself clear -- if you still want a full example of how this firehose class could be used please tell me and I'll try writing a simple app for this. – Serafeim Jul 13 '15 at 09:57