Question

I have a model called Item, with m2m relation to User ("owner").

For each item, i need to count users who own it. That's easy enough with annotate()

But then i need to calculate ratio between owners of specific gender and total owner count for each item. For example if, 2 males own the item out of 5 users, the ration is 0.4.

What's the best way to do that?

Was it helpful?

Solution

To do this with the ORM, you need conditional aggregates, which aren't supported in Django. http://www.voteruniverse.com/Members/jlantz/blog/conditional-aggregates-in-django proposes a hacky solution that might work.

If you don't need to sort by the ratio, then you can make two calls to annotate, and then compute the ratio in Python. Something like:

items = Item.objects.annotate(ucount=Count('users')).annotate(ccount=CountIf(<condition>))
for item in items:
    item.ratio = item.ucount / item.ccount

If you don't want to do that, I'd recommend using the extra() method and some custom sql to get the extra info you want. Documentation for that method is on the Django Queryset API documentation page.

OTHER TIPS

Just on top of my head, something like the following could work. Iterate on it to get your perfect solution if you wish:

items = Item.objects.annotate(Count('users'))

for item in items:
    total = item.users__count
    num_males = item.users.filter(gender='M').count()
    num_females = item.users.filter(gender='F').count()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top