Question

I have a queryset at the moment that returns the number items in a model ordered by the number of people watching it. So I have a m2m field representing this link.

Ie:

#models.py
class MyModel(models.Model):
...
watchers = models.ManyToManyField(User, blank=True)

I would count the number of occurrences and order them by count in a default manager which was then used by the view.

Now I'm going over to using django-notification, using 'notification.ObservedItem' to allow users to watch an instance if MyModel.

So in my view when a user posts some content I have something like this:

notification.observe(object, request.user, 'new_object')

This works well.

Now, how can I generate a queryset representing all the objects of class MyModel, ordered by the number of people 'observing' them?

Was it helpful?

Solution

You can accomplish that by using annotations:

from django.db.models import Count
MyModel.objects.annotate(num_users=Count('watchers')).order_by('num_users')

OTHER TIPS

The problem is that django-notification uses generic foreign keys.

So I've redefined my watchers field:

watchers = generic.GenericRelation(notification.ObservedItem)

Then I can get all the watchers for a specific instance of MyModel.

$x = MyModel.objects.get(id=1)
$x.watchers.all()
$[<ObservedItem: ObservedItem object>, <ObservedItem: ObservedItem object>, <ObservedItem: ObservedItem object>]
$x.watchers.count()
$3

Close but no cigar. I wanted to do was something like this:

MyModel.objects.annotate(count=Count('watchers')).order_by('count')

Which is something that Django can't do, according to the docs.

Django's database aggregation API doesn't work with a GenericRelation.

Not to worry, I think this will probably help:

http://charlesleifer.com/blog/generating-aggregate-data-across-generic-relations/

Repo is here:

https://github.com/coleifer/django-generic-aggregation

I've not tried it out yet...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top