Search code examples
djangodjango-modelsdjango-queryset

Django - Is it possible to prefetch multiple filters of a single field for a queryset?


I know you can prefetch a single filtered queryset E.g.

Parent.objects.all()
.prefetch_related(
  Prefetch("child_set", queryset=Child.objects.filter(type="A")
)

That way running obj.child_set.all().count() will return the count of related A Childs without running another query.

But what if I wanted to have the B count too? So the following would take 2 queries - can I somehow prefetch them both?

return {
  "a_count": obj.log_set.filter(type="A").all().count(),
  "b_count": obj.log_set.filter(type="B").all().count(),
}

Edit: I've tried

Parent.objects.all()
.prefetch_related(
  Prefetch("child_set", queryset=Child.objects.filter(type="A"),
  Prefetch("child_set", queryset=Child.objects.filter(type="B")
)

But that gives me the following error when I try to access the object:

{
    "detail": "Not found."
}

Solution

  • With regards to your main question, you can use Prefetch..[Django-doc] object on the same field with different filters, but assign them with different to_attr values like this:

    from django.db.models import Prefetch
    
    
    Parent.objects.prefetch_related(
        Prefetch(
            "child_set", 
            queryset=Child.objects.filter(type="A"), 
            to_attr="child_set_a"
        ),
        Prefetch(
            "child_set", 
            queryset=Child.objects.filter(type="B"), 
            to_attr="child_set_b"
        ),
    )