I have a few categories and I would like to list the products per category

I have a few categories and I would like to list the products per category in the format below (categories is an FK to products):

Category 1

bunch of products

....

Category N

bunch of products

I have tried many ways but so far I only get the categories but not the products to show in my HTML.

I m new in django cant find the solution

in models.py:

from django.utils import timezone
from distutils.command.upload import upload
from email.policy import default
from django.db import models
from django.contrib.auth.models import User

# Create your models here.


class Main_Category(models.Model):
    name=models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Sub_Category(models.Model):
    main_category=models.ForeignKey(Main_Category,on_delete=models.CASCADE)
    name=models.CharField(max_length=100)
    def __str__(self):
        return self.name
    
        
class Product(models.Model):
    Status=('publish','publish'),('draft','draft')

    product_id=models.AutoField
    name=models.CharField(max_length=50)
    category=models.ForeignKey(Main_Category,on_delete=models.CASCADE,null=True,default="")
    sub_category=models.ForeignKey(Sub_Category,on_delete=models.CASCADE,null=True,default="")
    price=models.IntegerField(default=0)
    des=models.CharField(max_length=2000)
    status=models.CharField(choices=Status,max_length=200)
    delivery=models.IntegerField(null=True)
    date=models.DateTimeField()
    image=models.ImageField(upload_to="shop/images",default="Status")
    slug=models.CharField(max_length=150)
    def __str__(self):
        return self.name
    @property
    def get_products(self):
        return Product.objects.filter(categories__title=self.name)


class Orders(models.Model):
    user=models.ForeignKey(User,on_delete=models.CASCADE)
    amount=models.CharField(max_length=55)
    Order_id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=55)
    email=models.CharField(max_length=30)
    address=models.CharField(max_length=200)
    phone=models.CharField(max_length=15)
    city=models.CharField(max_length=20)
    state=models.CharField(max_length=20)
    zip_code=models.CharField(max_length=10)
    date=models.DateTimeField(default=timezone.now)
    def __str__(self):
        return self.user.username

class OrderItem(models.Model):
    order=models.ForeignKey(Orders,on_delete=models.CASCADE)
    product=models.CharField(max_length=200)
    image=models.ImageField(upload_to="shop/images/cust_image")
    quantity=models.CharField(max_length=20)
    price=models.CharField(max_length=15)
    total=models.CharField(max_length=1000)
    def __str__(self):
        return self.order.user.username







Views.py

from django.shortcuts import redirect, render
from .models import Main_Category, Product,Sub_Category,Orders,OrderItem
from django.core.paginator import Paginator
from django.contrib.auth.decorators import login_required
from cart.cart import Cart
from django.contrib.auth.models import User,auth
from django.contrib import messages

# Create your views here.




def index(request):
    allproduct=Product.objects.all() ###filter(publish)which product you want to display in homepage
    main_category=Main_Category.objects.all().order_by('-id')
    categoryID = request.GET.get('main_category')
    if categoryID:
        allproduct=Product.objects.filter(sub_category=categoryID)
    else:
        allproduct=Product.objects.all()

    paginator=Paginator(allproduct,5)
    page_number=request.GET.get('page')
    pagedata=paginator.get_page(page_number)
    totalpage=pagedata.paginator.num_pages
    print(allproduct)
    context= {'allproduct':allproduct,
              'main_category':main_category,
              'allproduct':pagedata,
              'totalpagelist':[n+1 for n in range(totalpage)]
              
    }


   
    return render (request,"shop/index.html",context)











in html:
  <div class="col">
          <div class="row ">
              

              
            {% for product in allproduct %}
  
              <div class="col-6 col-sm-6 col-md-6 col-lg-3">
               
                  <div class="card">
                      <img class="card-img-top " src='/media/{{product.image}}' alt="Card image cap">
                      <div class="card-body">
                          <h4 class="card-title">{{product.name}}</h4>
                          <p class="card-text">{{product.des |truncatechars:50}}</p>
                          <p class="card-text">{{product.time}}</p>
                          <div class="row">
                              <div class="col">
                                  <a class=" btn btn-primary" href="{% url 'cart_add' product.id %}">Add to cart</a>
                                 
                                  <a  class="btn btn-danger ">{{product.price}} Tk</a>
                                </div>
                                
                              </div>
                              
                          </div>
                      </div>        
                  </div>
                  {% endfor %}
              </div>
             

To do it, I think you should change the ForeignKey to a OnetoOneField in the Product class. Then you can access it from the Category and Sub_Category class.

But to do it with the current setup, you would have to go through each category and filter the products by it.

So…

categories = Category.objects.all()
list = []
for cat in categories:
    products = Products.objects.filter_by(category=cat)
    dics = {"name":cat, "products":products}
    list.append(dics)

then return the variable list to the html template

Back to Top