[ACCEPTED]-Django ORM: Selecting related set-orm

Accepted answer
Score: 23

Time has passed and this functionality is 11 now available in Django 1.4 with the introduction 10 of the prefetch_related() QuerySet function. This function 9 effectively does what is performed by the 8 suggested qbind function. ie. Two queries are 7 performed and the join occurs in Python 6 land, but now this is handled by the ORM.

The 5 original query request would now become:

polls = Poll.objects.filter(category = 'foo').prefetch_related('choice_set')

As 4 is shown in the following code sample, the 3 polls QuerySet can be used to obtain all Choice objects 2 per Poll without requiring any further database 1 hits:

for poll in polls:
    for choice in poll.choice_set:
        print choice
Score: 17

Update: Since Django 1.4, this feature is built 21 in: see prefetch_related.

First answer: don't waste time 20 writing something like qbind until you've 19 already written a working application, profiled 18 it, and demonstrated that N queries is actually 17 a performance problem for your database 16 and load scenarios.

But maybe you've done 15 that. So second answer: qbind() does what 14 you'll need to do, but it would be more 13 idiomatic if packaged in a custom QuerySet 12 subclass, with an accompanying Manager subclass 11 that returns instances of the custom QuerySet. Ideally 10 you could even make them generic and reusable 9 for any reverse relation. Then you could 8 do something like:

Poll.objects.filter(category='foo').fetch_reverse_relations('choices_set')

For an example of the 7 Manager/QuerySet technique, see this snippet, which 6 solves a similar problem but for the case 5 of Generic Foreign Keys, not reverse relations. It 4 wouldn't be too hard to combine the guts 3 of your qbind() function with the structure 2 shown there to make a really nice solution 1 to your problem.

Score: 15

I think what you're saying is, "I want all 2 Choices for a set of Polls." If so, try 1 this:

polls = Poll.objects.filter(category='foo')
choices = Choice.objects.filter(poll__in=polls)
Score: 1

I think what you are trying to do is the 11 term "eager loading" of child 10 data - meaning you are loading the child 9 list (choice_set) for each Poll, but all 8 in the first query to the DB, so that you 7 don't have to make a bunch of queries later 6 on.

If this is correct, then what you are 5 looking for is 'select_related' - see https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related

I 4 noticed you tried 'select_related' but it 3 didn't work. Can you try doing the 'select_related' and 2 then the filter. That might fix it.


UPDATE: This 1 doesn't work, see comments below.

More Related questions