Search code examples
pythondjangopython-2.7django-1.4

Do QuerySet operations on prefetched relationships hit the database?


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.


Solution

  • 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.)