Django: Does prefetch_related() follow reverse relationship lookup?

DjangoDjango ModelsDjango Queryset

Django Problem Overview


I've tried prefetch_related() in django 1.4 from trunk and can't make it to prefetch reverse lookup.

My simplified models (each book has many prices):

class Book(models.Model):
    # some fields

class Price(models.Model):
    book = models.ForeignKey(Book)

My view's query:

books = Book.objects.prefetch_related('price')

Then, I got the AttributeError message:

AttributeError: Cannot find 'price' on Book object, 'price' is an invalid parameter to prefetch_related()

How to make it work? Thanks.

Django Solutions


Solution 1 - Django

Define a related name:

class Price(models.Model):
    book = models.ForeignKey(Book, related_name='prices')

and then use it:

books = Book.objects.prefetch_related('prices')

Solution 2 - Django

When you do not have defined a related_name for the relation, the reverse relation has _set appended. This is the case when accessing the reverse relation from an object (e.g. some_book.price_set.all()), but this also works on prefetch_related:

books = Book.objects.prefetch_related('price_set')

Note that this seems different from filter, which does accept the name of the other model without _set (e.g. Books.objects.filter(price__currency='EUR')).

The above was tested with 1.11.8 (not on this specific code, but on my own, similar code).

Alternatively, you can add a related_name, as shown by Jan Pöschko above.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTianissimoView Question on Stackoverflow
Solution 1 - DjangoJan PöschkoView Answer on Stackoverflow
Solution 2 - DjangoMatthijs KooijmanView Answer on Stackoverflow