使用Django-mptt实现选中分类时展示该分类及所有子分类商品
解决方案
你需要修改视图层的商品过滤逻辑,使用django-mptt自带的后代节点查询方法实现需求,具体改动如下:
1. 修改views.py中的product_list函数
找到分类过滤的代码段,将原有的精确匹配分类逻辑,替换为匹配当前分类+所有子分类:
def product_list(request, category_slug=None): category = None categories = Category.objects.all() products = Product.objects.filter(available=True).order_by('-created') if category_slug: category = get_object_or_404(Category, slug=category_slug) # 新增代码:获取当前分类及所有层级的子分类集合 target_categories = category.get_descendants(include_self=True) # 过滤条件改为商品分类在上述集合中 products = products.filter(category__in=target_categories) return render(request, 'shop/shop.html', {'category': category, 'categories': categories, 'products': products})
逻辑说明
get_descendants()是django-mptt提供的内置方法,会单次查询数据库拿到当前节点下所有层级的子节点,符合你使用mptt减少数据库查询的需求- 加
include_self=True参数是为了同时匹配直接挂在当前分类下的商品,比如如果有商品直接归属于「服装」分类,也会正常显示
2. 可选修正:models.py的缩进问题
你当前贴出的Category类代码存在缩进错误,MPTTMeta和内部的Meta类应该是Category的子类,修正后写法如下:
class Category(MPTTModel): name = models.CharField(max_length=200, db_index=True) slug = models.SlugField(max_length=200, db_index=True, unique=True) parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') # 以下类的缩进调整为Category的内部类 class MPTTMeta: order_insertion_by = ['name'] class Meta: ordering = ('name',) verbose_name = 'Категория' verbose_name_plural = 'Категории' def get_absolute_url(self): return reverse('shop:product_list_by_category', args=[self.slug]) def __str__(self): return self.name
前端模板不需要做任何修改,调整完上述代码后即可实现父分类页展示所有子分类商品的需求。
内容的提问来源于stack exchange,提问作者sk1p
相关产品推荐
相关产品推荐

