如何在Django REST Framework的get_queryset中添加Q查询实现过滤结果内搜索
实现方案
你只需要把原有过滤逻辑改成链式调用的形式,再把搜索逻辑放在过滤流程的最后一步,就能保证搜索只在已经过滤完成的结果集里执行,不会触发全量数据库查询。同时还能解决你原有嵌套if写法只能在三个参数同时传递时才生效的问题,支持任意参数组合使用。
完整的视图代码如下:
from django.db.models import Q class ProductAPIView(ListAPIView): permission_classes = [AllowAny] serializer_class = ProductSerializer queryset = Product.objects.all() pagination_class = CustomPagination def get_queryset(self): # 拿到基础查询集 queryset = super().get_queryset() # 逐个处理过滤参数,链式叠加过滤条件 brand = self.request.GET.get('brand', None) if brand: brand_values = brand.split(",") queryset = queryset.filter(brand__name__in=brand_values) sub_category = self.request.GET.get("sub_category", None) if sub_category: sub_category_values = sub_category.split(",") queryset = queryset.filter(sub_category__name__in=sub_category_values) warranty = self.request.GET.get("warranty", None) if warranty: warranty_values = warranty.split(",") queryset = queryset.filter(warranty__in=warranty_values) # 最后处理搜索逻辑,仅在已过滤的结果中匹配关键词 search_keyword = self.request.query_params.get('search', None) if search_keyword: queryset = queryset.filter( Q(category__name__icontains=search_keyword) | Q(brand__name__icontains=search_keyword) | Q(description__icontains=search_keyword) | Q(collection__name__icontains=search_keyword) | Q(name__icontains=search_keyword) | Q(variants__color__icontains=search_keyword) ).distinct() return queryset
修改完成后即可实现需求:
- 访问
localhost/api/products?brand=Samsung:仅返回三星品牌产品,和原有过滤逻辑一致 - 访问
localhost/api/products?search=frontload:全库搜索匹配关键词的产品,和原有搜索接口逻辑一致 - 访问
localhost/api/products?brand=Samsung&search=frontload:仅在三星品牌的产品中搜索匹配frontload的结果
内容的提问来源于stack exchange,提问作者Reactoo
相关产品推荐
相关产品推荐

