You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF中通过Category路由过滤关联Product对象的实现方案

解决方案

要实现分类详情接口通过查询参数过滤返回对应产品的通用逻辑,无需为每个分类硬编码规则,可通过重写分类视图的retrieve方法实现,具体步骤如下:

1. 修改分类视图(categories/views.py)

导入所需依赖,重写retrieve方法,根据请求是否携带过滤参数,动态返回分类数据或过滤后的产品数据:

from rest_framework.response import Response
from products.serializers import ProductSerializer
from .models import Category

class CategoriesAPIViewSet(viewsets.ModelViewSet):
    """ Standard ModelViewSet which implements CRUD with minor changes. """
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
    lookup_field = 'slug'

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        filter_params = request.query_params
        
        # 存在查询参数时,返回过滤后的产品
        if filter_params:
            # 查询当前分类下的所有产品
            products_queryset = instance.products.all()
            
            # 处理brand参数(按品牌slug过滤,可根据需求改为按name过滤)
            if 'brand' in filter_params:
                brand_slug = filter_params['brand']
                products_queryset = products_queryset.filter(brand__slug=brand_slug)
            
            # 可扩展其他过滤参数(如price、stock等)的处理逻辑
            serializer = ProductSerializer(products_queryset, many=True)
            return Response(serializer.data)
        
        # 无查询参数时,返回原分类及子分类数据
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

2. 可选:包含子分类产品过滤

如果需要返回当前分类及其所有子分类下的产品,利用MPTT的get_descendants方法扩展查询范围:

# 在retrieve方法的filter_params判断内,替换products_queryset的初始化代码
from products.models import Product

category_ids = [instance.id] + list(instance.get_descendants().values_list('id', flat=True))
products_queryset = Product.objects.filter(category_id__in=category_ids)

3. 通用过滤扩展(进阶)

如果需要支持更多类型的过滤参数(如价格区间、库存状态等),可以使用django-filter简化逻辑:

  • 安装依赖:pip install django-filter
  • 在项目settings.py的INSTALLED_APPS中添加'django_filters'
  • 定义过滤规则并在视图中使用:
# 在products/views.py或单独的filters.py中定义过滤规则
from django_filters.rest_framework import FilterSet, filters
from products.models import Product

class ProductFilter(FilterSet):
    brand = filters.CharFilter(field_name='brand__slug', lookup_expr='exact')
    min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
    max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')

    class Meta:
        model = Product
        fields = ['brand', 'min_price', 'max_price']

# 修改CategoriesAPIViewSet的retrieve方法中的过滤逻辑
filterset = ProductFilter(filter_params, queryset=products_queryset)
products_queryset = filterset.qs

这样无论访问哪个分类的详情接口,只要携带对应的查询参数,都会返回符合条件的产品,完全实现通用适配。


内容的提问来源于stack exchange,提问作者Antony_K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:05:40