davegri
davegri

Reputation: 2286

how do i limit prefetch_related in Django?

Say I've got image objects with a manytomany relationship with tag objects.

now, I'm creating a search view to display images and the tags are displayed for each image, obviously the smart thing to do is to prefetch the tags for the images.

however I'm only displaying 15 images every time but I do have to evaluate the whole queryset in order to display how many results overall there are. so I need to prefetch the tags only for the first 15 elements

If i prefetch the tags before slicing:

images = watson.filter(queryset, query).prefetch_related('tags')
amount = images.count()
images = images[:15]

this is very bad because there can be thousands of results and each result can have many tags.

but If I slice first:

images = watson.filter(queryset, query).prefetch_related('tags')[:15]
amount = images.count()

now I only prefetch tags for 15 results which is good however I can't count the results without making another query.

If i do this:

images = watson.filter(queryset, query)
amount = len(images)
images = images.prefetch_related('tags')[:15]

I still end up hitting the database twice because prefetch does a new db query.

basically I need to hit the database once to get all the images, but only prefetch the tags for the first 15.

Upvotes: 4

Views: 2192

Answers (1)

Alasdair
Alasdair

Reputation: 309039

Try calling count() first, then do prefetch_related() and slice the queryset.

images = watson.filter(queryset, query)
amount = images.count()
images = images.prefetch_related('tags')[:15]

This will do one query for the count, one for the first 15 images, and one to prefetch the tags. Calling count() is better than len() because it won't fetch the images you don't need.

Upvotes: 1

Related Questions