How to filter product by Category wise in Django?

Viewed 3710

I am trying to filter according to the category but it's displaying all products on each category page, but I want filter according to the category page, please check my code and let me know how I can do it.

here is my models.py file...

 class SubCategory(models.Model):
        subcat_name=models.CharField(max_length=225)
        subcat_slug=models.SlugField(max_length=225, unique=True)
        category = models.ForeignKey('Category', related_name='subcategoryies', on_delete=models.CASCADE, blank=True, null=True)

and here is my product models.py file...

    class Product(models.Model):
        name=models.CharField(max_length=225)
        slug=models.SlugField(max_length=225, unique=True)
        subcategory=models.ForeignKey('SubCategory', related_name='prosubcat', on_delete=models.CASCADE, blank=True, null=True)

        def __str__(self):
            return self.name


class ProductFilter(django_filters.FilterSet):
    name = django_filters.CharFilter(lookup_expr='icontains')
    class Meta:
        model = Product
        fields = ['saleprice', 'title','veg_non','brand','supplement']

def SubCategorySlugListAPIView(request, subcat_slug):
    category = Category.objects.all()
    subcategories = SubCategory.objects.all()
    product = Product.objects.all()
    brands=Brand.objects.all()
    f = ProductFilter(request.GET, queryset=Product.objects.all())
    supplement=Supplement.objects.all()
    featured=Product.objects.filter(featured=True).order_by('-created_at')[0:6]
    high = Product.objects.all().order_by('-saleprice')
    if subcat_slug:
        subcategory = get_object_or_404(SubCategory, subcat_slug=subcat_slug)
        productlist = product.filter(subcategory=subcategory)
        paginator = Paginator(productlist, 12)
        page_number = request.GET.get('page')
        product = paginator.get_page(page_number)
    template_name = 'mainpage/cat-products.html'
    context = {'product': product,
           'subcategories': subcategories, 'subcategory': subcategory, 'category': category, 'featured':featured, 'high':high, 'brands':brands, 'supplement':supplement, 'filter':f}
    return render(request, template_name, context)

i know there are need to merge these code f = ProductFilter(request.GET, queryset=Product.objects.all()) and this productlist = product.filter(subcategory=subcategory), using productlist i am getting product according to the category but when I do filter with filter then all products displaying on each category page. please merge both code and give me a correct solution for this.

2 Answers

You can try this.

def SubCategorySlugListAPIView(request, subcat_slug):
    
    # First get the category object.
    subcategory = get_object_or_404(SubCategory, subcat_slug=subcat_slug)
    
    # then filter the products on this category

    productlist =Product.objects.filter(subcategory=subcategory)

EDIT: There is no necessary to write extra filter method here. The basic thing you need is you need to get the single category object first and filter the products on this category from Product model.

def SubCategorySlugListAPIView(request, subcat_slug):
    subcategory = get_object_or_404(SubCategory, subcat_slug=subcat_slug)
    productlist = Product.objects.filter(subcategory=subcategory)
    paginator = Paginator(productlist, 12)
    page_number = request.GET.get('page')
    product = paginator.get_page(page_number)

    brands=Brand.objects.all()
    supplement=Supplement.objects.all()
    featured=Product.objects.filter(featured=True).order_by('-created_at')[0:6]
    high = Product.objects.all().order_by('-saleprice')            
       
    template_name = 'mainpage/cat-products.html'
    context = {'product': product,
           'subcategories': subcategories, 'subcategory': subcategory, 'category': category, 'featured':featured, 'high':high, 'brands':brands, 'supplement':supplement}
    return render(request, template_name, context)

Also you can filter the related products like this(other way)

subcategory = get_object_or_404(SubCategory, subcat_slug=subcat_slug)
productlist = subcategory.prosubcat.all()

for example:

In models.py

from django.db import models

class Category(model.Model):
    slug = models.SlugField(unique=True, max_length=50)

class Item(model.Model):
    category = models.ManyToManyField(Category,related_name='ITEM')

In views.py

from django.shortcuts import render, get_object_or_404
from .models import Category

def category_filter(request, slug):
    category = get_object_or_404(Category, slug=slug)
    data = category.ITEM.all()
    render(request, TEMPLATE_NAME, context={'data':data})

In urls.py

from django.urls import path
from .views import category_filter

urlpatterns = [
    path('category/<slug:slug>/', category_filter, name='Category'),
]

now if url is some thing like

localhost/category/froots/

all items with froot category will be displayed.

Related