djangodjango-treebeard

Retrieve all related objects of objects in a queryset


Asked another question yesterday. Unfortunately, the answer did not solve the problem so I thought I narrow the question down and ask again.

I have a Category model which is hierarchial(using django-treebeard). When I run example_category.get_descendants() the result I get is a MP_NodeQuerySet like the following

<MP_NodeQuerySet [<Category: shoes>, <Category: Sneakers>, <Category: laced_sneakers>]>

Out of this queryset I want to fetch every product related to each category and display in a view(DetailView).

My best bet has been

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)

        context["products_in_category"] = Category.objects.prefetch_related(
            Prefetch("products", queryset=self.object.get_descendants()))

    return context

Which results in the error

"Cannot resolve keyword 'category' into field. Choices are: depth, description, id, numchild, path, products, slug, title"

I guess I for some reason get the category back and not its products and I don't really know how to solve it.

Check out the old question for more context or just ask away!


Solution

  • Even if it worked, that query would return a queryset of Category instances.

    To get products that have one of the categories from get_descendants you can do

    from django.db.models import Subquery
    
    categories = example_category.get_descendants()
    Product.objects.filter(category__in=Subquery(categories.values("id"))
    

    Using Subquery is not required but it's a nice optimization to save you a db query.

    You can read more on it here