In Django 1.6 and earlier, it is not possible to avoid the extra queries. The prefetch_related
call effectively caches the results of a.photoset.all()
for every album in the queryset. However, a.photoset.filter(format=1)
is a different queryset, so you will generate an extra query for every album.
This is explained in the prefetch_related
docs. The filter(format=1)
is equivalent to filter(spicy=True)
.
Note that you could reduce the number or queries by filtering the photos in python instead:
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related("photo_set")
for a in someAlbums:
somePhotos = [p for p in a.photo_set.all() if p.format == 1]
In Django 1.7, there is a Prefetch()
object that allows you to control the behaviour of prefetch_related
.
from django.db.models import Prefetch
someAlbums = PhotoAlbum.objects.filter(author="Davey Jones").prefetch_related(
Prefetch(
"photo_set",
queryset=Photo.objects.filter(format=1),
to_attr="some_photos"
)
)
for a in someAlbums:
somePhotos = a.some_photos
For more examples of how to use the Prefetch
object, see the prefetch_related
docs.