本文讲解如何通过 django 的视图层预处理数据,将商品按分类分组并传递给模板,从而避免在模板中使用非法语法操作变量(如定义列表、条件去重等),实现清晰、可维护的分类商品表格展示。
在 Django 模板中,无法执行赋值操作(如 {% used_catego
ry = [] %})或运行复杂逻辑(如动态列表追加、对象比较判断)——这正是你遇到 TemplateSyntaxError: Invalid block tag 的根本原因。Django 模板语言是故意限制逻辑能力的设计,其核心原则是:视图负责数据准备与业务逻辑,模板仅负责展示。
✅ 正确做法是:在视图中完成「按分类聚合商品」的工作,并将结构化数据传入模板。
首先,为 ForeignKey 显式指定 related_name,便于反向查询:
class ShopItem(models.Model):
itemName = models.CharField(max_length=64)
price = models.IntegerField()
category = models.ForeignKey(
Category,
on_delete=models.CASCADE,
related_name='items' # ← 关键:允许 category.items.all() 获取所有商品
)使用 prefetch_related 提升性能,并按分类聚合:
# views.py
from django.shortcuts import render
from .models import Category
def shop_items_by_category(request):
# 获取所有有商品的分类,并预加载其关联商品
categories = Category.objects.prefetch_related('items').annotate(
item_count=models.Count('items')
).filter(item_count__gt=0).order_by('category')
return render(request, 'shop/items_by_category.html', {
'categories': categories
})? prefetch_related('items') 会一次性查出所有分类及其商品,避免 N+1 查询;filter(item_count__gt=0) 确保只显示有商品的分类。
| {{ category.category }} | ||
|---|---|---|
| {{ item.itemName }} | {{ item.price }} ¥ | |
通过将数据组织逻辑移至视图层,你不仅解决了语法错误,还让代码更符合 Django 的 MVT 架构精神:职责分离、易于测试、便于复用。