How to get all descendants of a node with Django mptt?
Question:
I would like my categories to show all items in that category including descendant categories, so the parent category contains all items for subcategories.
I have tried adding this method to my Category class in models.py
def get_all_products(self):
# To display all items from all subcategories
return Product.objects.filter(category__in=Category.objects.get_descendants(include_self=True))
And added this to my template.html, but it does’t work. What am I doing wrong?
<li>{{ product.product_name }}</li>
{% empty %}
<li>No items</li>
{% endfor %}
Answers:
I’ve realised where I was going wrong, the correct code is:
def get_all_products(self):
# To display all items from all subcategories
return Product.objects.filter(category__in=self.get_descendants(include_self=True))
{% for product in product.get_all_products %}
<li>{{ product.product_name }}</li>
{% empty %}
<li>No items</li>
{% endfor %}
In view function I use:
products = models.Product.objects.filter(category__in=category.get_descendants(include_self=True))
For example, you can get all descendants of a category with get_descendants() in views.py
as shown below. *If include_self
is True
, the QuerySet
will also include the model instance itself:
# "views.py"
from django.http import HttpResponse
from .models import Category, Product
def test(request):
categories = Category.objects.get(name="Food").get_descendants()
print(categories)
# <TreeQuerySet [<Category: Meat>, <Category: Fish>]>
categories = Category.objects.get(name="Food").get_descendants(include_self=True)
print(categories)
# <TreeQuerySet [<Category: Food>, <Category: Meat>, <Category: Fish>]>
products = Product.objects.filter(category__in=categories)
print(products)
# <QuerySet [<Product: Beef>, <Product: Pork>, <Product: Salmon>
return HttpResponse("Test")
I would like my categories to show all items in that category including descendant categories, so the parent category contains all items for subcategories.
I have tried adding this method to my Category class in models.py
def get_all_products(self):
# To display all items from all subcategories
return Product.objects.filter(category__in=Category.objects.get_descendants(include_self=True))
And added this to my template.html, but it does’t work. What am I doing wrong?
<li>{{ product.product_name }}</li>
{% empty %}
<li>No items</li>
{% endfor %}
I’ve realised where I was going wrong, the correct code is:
def get_all_products(self):
# To display all items from all subcategories
return Product.objects.filter(category__in=self.get_descendants(include_self=True))
{% for product in product.get_all_products %}
<li>{{ product.product_name }}</li>
{% empty %}
<li>No items</li>
{% endfor %}
In view function I use:
products = models.Product.objects.filter(category__in=category.get_descendants(include_self=True))
For example, you can get all descendants of a category with get_descendants() in views.py
as shown below. *If include_self
is True
, the QuerySet
will also include the model instance itself:
# "views.py"
from django.http import HttpResponse
from .models import Category, Product
def test(request):
categories = Category.objects.get(name="Food").get_descendants()
print(categories)
# <TreeQuerySet [<Category: Meat>, <Category: Fish>]>
categories = Category.objects.get(name="Food").get_descendants(include_self=True)
print(categories)
# <TreeQuerySet [<Category: Food>, <Category: Meat>, <Category: Fish>]>
products = Product.objects.filter(category__in=categories)
print(products)
# <QuerySet [<Product: Beef>, <Product: Pork>, <Product: Salmon>
return HttpResponse("Test")