简体   繁体   中英

django prefetch_related across mutliple one-to-many relations with filtering conditions

I would like to to a prefetch_related query to get my models and all related models by following one-to-many relations, but with a filtering condition. My goal is to use prefetch_related to obtain all my models and related models in one django query (thus not hitting the database when iterating through related models). I need to go in the one-to-many direction.

Say I have the following simple models of Library having many Books having many Pages.

from django.db import models

class Library(models.Model):
    name = models.CharField(max_length=50)

class Book(models.Model):
    title = models.CharField(max_length=50)
    genre = models.CharField(max_length=50)
    library = models.ForeignKey(Library, on_delete=models.CASCADE)

class Page(models.Model):
    content = models.TextField()
    book = models.ForeignKey(Book, on_delete=models.CASCADE)

I know I can do models.Library.objects.prefetch_related('book_set__page_set') to get everything one-shot, but what if I want to restrict to book with genre='fantasy' ? How can I add this filter condition in my relation-spanning prefetch query?

You'll want to follow the instructions here:

https://docs.djangoproject.com/en/2.2/ref/models/querysets/#prefetch-objects

Basically you'll do something like this

books_query = Books.objects.filter(genre="fantasy")
pf = Prefetch("book_set", queryset=books_query)
Library.objects.prefetch_related(pf).get().book_set.all()

Complementing @themanatuf answer which was missing the prefetching of related Page models. Query code below will prefetch all Library models with their related Books and Pages, but restricting to Book genre='fantasy':

pf_queryset = models.Book.objects.filter(genre="fantasy").prefetch_related("page_set")
pf = Prefetch("book_set", queryset=pf_queryset)
models.Library.objects.prefetch_related(pf).all()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM