tags:

views:

69

answers:

2

I have the following Django models:

class Foo(models.Model):
    title = models.CharField(_(u'Title'), max_length=600)

class Bar(models.Model):
    foo = models.ForeignKey(Foo)
    eg_id = models.PositiveIntegerField(_(u'Example ID'), default=0)

I wish to return a list of Foo objects which have a reverse relationship with Bar objects that have a eg_id value contained in a list of values. So I have:

id_list = [7, 8, 9, 10]
qs = Foo.objects.filter(bar__eg_id__in=id_list)

How do I order the matching Foo objects according to the number of related Bar objects which have an eg_id value in the id_list?

+1  A: 

Use Django's lovely aggregation features.

from django.db.models import Count
qs = Foo.objects.filter(
           bar__eg_id__in=id_list
      ).annotate(
           bar_count=Count('bar')
      ).order_by('bar_count')
Daniel Roseman
Thanks. Only recently upgraded from Django 1.0 so the aggregation feature is still rather new to me.
msanders
As a follow up. I tried to add the filter as a property into my my "Foo" model object. even though i import the 'Bar' model, django shell says 'bar' in Count('bar') is not identified. Why does it work in my view.py but not in my model.py? thanks!
David Hsu
+1  A: 

You can do that by using aggregation, and more especifically annotation and order_by.

In your example, it would be:

from django.db.models import Count

id_list = [7, 8, 9, 10]
qs = Foo.objects.filter(bar__eg_id__in=id_list)
qs = qs.annotate(count=Count("bar"))
qs = qs.order_by('-count')
DZPM