1๐
You can use product_set
as related name created by default in Django, or you can better create a related name yourself. A product belongs to a category, but a category can have many products. Follow this principle and make your queries human readable.
For this purpose set the related name for category
in the class Product
:
category = models.ForeignKey(
Category,
on_delete=models.CASCADE,
related_name='products'
)
Now in your views.py
you have to make some changes.
class CategoryDetailView(DetailView):
model = Category
# remove the line below
category_products = Category.product_set.all()
# don't prefix the fields like this, it's ugly and redundant
# call it just slug, not category_slug, adjust in urls.py
slug_url_kwarg = "category_slug"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# where did you get self.categories?
context['categories'] = self.categories
# and this won't work anymore too
context['category_products'] = self.category_products
return context
In the CategoryDetailView
youโre going to display just one Category. It is detailed view โ it implies just a single object. Therefore youโre not using something like categories. The object is available in the method. This is how we rewrite it:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
products = self.object.products.all()
context['products'] = products
return context
5๐
The real problem is that the original poster tried to call the RelatedManager.all() function from the class instead of from an instance.
category_products = Category.product_set.all()
Category is the class name. Since it is the class, it does does not and cannot know about the related products of a single instance.
You have to call the RelatedManagers.all() function from an instance, not the class itself.
- [Django]-Django โ Model class interfaces?
- [Django]-Django 1.9: Should I avoid importing models during `django.setup()`?
2๐
This may help:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
instance = self.get_object()
context['categories'] = self.categories
context['category_products'] = instance.product_set.all()
return context