0

Let's say I query Workplaces in a City and prefetch all their Workers, which is a many-to-many relationship:

workplaces = list(city.workerplace_set.filter(num_employees__lte=350).prefetch_related('Worker'))

If I use any QuerySet operation on Workers from any of the Workplaces, will the database be hit or not? I could not make out a clear answer from the docs.

workplaces_with_interns = [workplace for workplace in workplaces 
                           # is this filter going to query the database?
                           if workplace.worker_set.filter(salary=0).exists()]

PS: someone is probably going to point out that I can reach the same answer by simply making a query for city.workerplace_set instead of making it a list. Yes, I know, but that is not possible because I am caching the workplaces so that the database is not hit every time the function that does all this is called.

dabadaba
  • 9,064
  • 21
  • 85
  • 155

1 Answers1

0

Yes. This will hit the database because you are running a specific query - exists on a filter - that was not present in the original prefetch.

In your case, since you already have the workers, it would be better to filter them in Python:

[workplace for workplace in workplaces 
 if any(w.salary == 0 for w in workplace.worker_set.all())]

Alternatively, if this is the only reason you need the prefetch, you could use a Prefetch object in the original query to only fetch the workers with 0 salary.

(Just noticed you are using 1.4, which doesn't have Prefetch objects. You should definitely upgrade; not only for that reason, but mainly because 1.4 is very old and unsupported, and is therefore certainly a security risk.)

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895