Django新手求助:如何按主分类分组展示对应产品
问题解决:Django按「分类名称+对应产品列表」展示内容
问题描述
我是Django新手,希望按照「分类名称+对应产品列表」的格式展示产品(主分类Main_Category是Product模型的外键),但尝试多种方法后,仅能在页面中显示分类,无法展示对应产品。以下是相关代码:
模型代码(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 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)
HTML模板代码
{% 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 %}
解决方案
核心问题分析
- 视图未按分类组织产品数据,仅传递了独立的分类和产品列表,无法建立关联
Product模型中get_products属性逻辑错误,引用了不存在的字段- 模板仅遍历产品列表,未关联分类展示对应内容
- 模型和模板存在多处字段名不匹配、语法错误
分步修正
1. 修复模型错误
- 修正
Product的Status定义(嵌套元组格式错误) - 补全
product_id的主键定义 - 删除无用且错误的
get_products属性
修改后的Product模型片段:
class Product(models.Model): # 修正Status格式 Status = (('publish', 'publish'), ('draft', 'draft')) # 补全主键定义 product_id = models.AutoField(primary_key=True) name=models.CharField(max_length=50) category=models.ForeignKey(Main_Category,on_delete=models.CASCADE,null=True,default="") # 其他字段保留...
2. 重构视图,按分类关联产品
修改index视图,预加载分类及对应产品,减少数据库查询:
def index(request): # 预加载主分类及其关联的产品,避免N+1查询 main_categories = Main_Category.objects.all().order_by('-id').prefetch_related('product_set') categoryID = request.GET.get('main_category') context = {'main_categories': main_categories} # 处理分类筛选逻辑(可选) if categoryID: filtered_products = Product.objects.filter(category=categoryID, status='publish') paginator = Paginator(filtered_products, 5) page_number = request.GET.get('page') pagedata = paginator.get_page(page_number) totalpage = pagedata.paginator.num_pages context.update({ 'filtered_products': pagedata, 'totalpagelist': [n+1 for n in range(totalpage)], 'selected_category': categoryID }) return render(request, "shop/index.html", context)
3. 修改模板,实现「分类+产品」展示结构
调整模板,先遍历分类,再展示对应产品:
<!-- 遍历所有主分类,展示分类名及对应产品 --> {% for category in main_categories %} <div class="category-block"> <h2>{{ category.name }}</h2> <div class="row"> {% for product in category.product_set.all %} {% if product.status == 'publish' %} <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="{{ product.name }}"> <div class="card-body"> <h4 class="card-title">{{ product.name }}</h4> <p class="card-text">{{ product.des|truncatechars:50 }}</p> <!-- 修正字段名:time改为date --> <p class="card-text">{{ product.date }}</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> {% endif %} {% empty %} <p>该分类暂无已发布产品</p> {% endfor %} </div> </div> {% endfor %} <!-- 可选:展示筛选后的分页产品列表 --> {% if filtered_products %} <div class="filtered-results"> <h2>分类筛选结果</h2> <div class="row"> {% for product in filtered_products %} <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="{{ product.name }}"> <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.date }}</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> <!-- 分页导航 --> <div class="pagination"> {% for page in totalpagelist %} <a href="?page={{ page }}&main_category={{ selected_category }}">{{ page }}</a> {% endfor %} </div> </div> {% endif %}
内容的提问来源于stack exchange,提问作者Arafa Jhalak
相关产品推荐
相关产品推荐

