Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django count related objects

Tags:

python

django

How can I count related objects in Django (in less than N queries, where N is number of object).

To clarify, let's say I have tables A and B. Every B is connected to exactly one A. Approach I tried:

A.objects.select_related().filter(attr=val)
A[i].B_set.count()

Of course, for every A[i] I want to find out number of B objects Django executes one query.

So the question is - is there a way to optimize that?

like image 363
ivan Avatar asked Aug 25 '10 20:08

ivan


People also ask

What is Select_related in Django?

Django offers a QuerySet method called select_related() that allows you to retrieve related objects for one-to-many relationships. This translates to a single, more complex QuerySet, but you avoid additional queries when accessing the related objects. The select_related method is for ForeignKey and OneToOne fields.

How does Django count foreign keys?

You can use . annotate() to get the count of answers associated with each question . By doing this, each question object will have an extra attribute number_of_answers having the value of number of answers associated to each question .

What is QuerySet?

A QuerySet is a collection of data from a database. A QuerySet is built up as a list of objects. QuerySets makes it easier to get the data you actually need, by allowing you to filter and order the data. In this tutorial we will be querying data from the Members table.

Does Django ORM support subquery?

¶ Django allows using SQL subqueries.


2 Answers

I have not tried how many queries are executed, but the Django way should be using annotate(). For example:

from django.db.models import Count

q = A.objects.select_related('B').annotate(num_B=Count('B'))
print A[0].num_B
like image 84
Bernhard Vallant Avatar answered Sep 23 '22 12:09

Bernhard Vallant


I have to answer my own question :) If object of A is queried something like this:

A.objects.select_related().filter(atrr=val).annotate(n_b=models.Count('B'))

This creates very long query, but at least there is just one.

like image 28
ivan Avatar answered Sep 19 '22 12:09

ivan