Search code examples
pythondjangodjango-filter

How to filter products by category in Django?


There is a product page. I need to display only those products that belong to the same category.I tried to use get_queryset(), but got an error Unsupported lookup 'slug' for SlugField or join on the field not permitted.. How can I solve this?

My code:

model.py

class Category(models.Model):
    name = models.CharField(max_length=50, verbose_name="Ім'я категорії")
    slug = models.SlugField(unique=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("category_detail",kwargs={'slug': self.slug})


class Product(models.Model):
    category = models.ForeignKey(Category, verbose_name='Категорія', on_delete=models.CASCADE)
    title = models.CharField(max_length=150, verbose_name='Ім\'я продукта')
    slug = models.SlugField(unique=True)
    product_code = models.IntegerField(default='0003001', verbose_name='Код продукту', blank=True, null=False)
    img = models.ImageField(verbose_name='Фотокартка')
    qty_product = models.IntegerField(default=1, verbose_name='Кількість товару')
    price = models.DecimalField(max_digits=5, decimal_places=0, verbose_name='Ціна')
    description = models.CharField(max_length=3000, verbose_name='Опис')

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('product_detail', kwargs={'slug': self.slug})

views.py

class CategoryDetailView(DetailView):
    model = Category
    queryset = Category.objects.all()
    template_name = "mainapp/product-category.html"
    slug_url_kwarg = 'slug'
    context_object_name = 'products'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        category = self.get_object()
        context['categories'] = self.model.objects.all()
        context['products'] = Product.objects.all()
        context['category_products'] = category.product_set.all()
        return context

    def get_queryset(self):
        return Product.objects.filter(slug__slug=self.kwargs['slug'])

Solution

  • There is no need to do filtering here, and definitely not on the Product model: this is a DetailView [Django-doc] for the Category model,s o you can work with:

    class CategoryDetailView(DetailView):
        model = Category
        template_name = 'mainapp/product-category.html'
        context_object_name = 'category'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['categories'] = self.model.objects.all()
            context['products'] = Product.objects.all()
            context['category_products'] = self.object.product_set.all()
            return context

    This will pass the Category for the given slug as category to the template, and the related Products as category_products.