I have 3 models Category, Make and Variant connected as below
class Category:
title = models.CharField(...
class Make:
title = models.CharField(...
category = models.ForeignKey(Category...
class Variant:
title = models.CharField(...
make = models.ForeignKey(Make....
Since I wanted to show all Categories and details of Make (available or None) for each Category, used a reverse lookup for LEFT OUTER JOIN like this:
which is working fine. However, I am not able to access the variant_set for each Make in the above query from Category model. I tried using prefetch_related but the join is not made as Category model will not know Variant model.
How to access count of variants from Category model for each Make?
I’m not sure I understand exactly what you want in your queryset.
A queryset for Category is going to annotate one value for each row of Category. But what you’ve written leads me to believe that you want all of the related Make objects annotated with the count of Variant related on each.
Are you looking to get all the Make objects for one Category object, with the count of Variant for each Make?
Django automatically creates a related_name using the name of model with the suffix _set. However I am not able to access the child_set of right table (Make model) in the above mentioned query.
I am able to do the same using raw SQL but not through ORM.
select A.title as Category, B.title as Make, count(C.id) as Variants
from Category A left outer join Make B
on
A.id = B.id
left outer join Variant C
on
B.id = C.id
group by A.title, B.title
I am not aware of any means to annotate a reference in a prefetch_related.
However, the issue with your construction as far as the ORM is concerned, is that you’re not showing the case where you have multiple Make for a single Category. (This is a many-to-one relationship, with Make on the “many” side.)
So what do you want to see if Category3 has both Make2 and Make3 related to it? If you want to see two separate rows for Category3, then the ORM is not going to provide a distinct “single-query” solution for you. You will need to issue two queries and join the results yourself. (Note: That’s actually what prefetch_related does. It reduces the number of queries from N+1 to 2, not N+1 to 1.)