无需新增端点实现Documents的.filter()与.all()功能咨询
无需新增端点实现关联字段过滤的Django ModelViewSet方案
不用新增端点就能搞定,给你两个简洁方案,都是基于现有ModelViewSet扩展:
方案一:用django-filter(推荐,功能全)
默认的filter_fields确实不支持关联字段,官方推荐用django-filter来处理复杂过滤:
- 先装包:
pip install django-filter - 在
settings.py里配置:INSTALLED_APPS = [ # 其他已有的app 'django_filters', ] REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': [ 'django_filters.rest_framework.DjangoFilterBackend', ], } - 定义过滤规则类:
from django_filters import rest_framework as filters from .models import Document class DocumentFilter(filters.FilterSet): # 关联字段用`field_name`指定外键的链式访问 customer_id = filters.NumberFilter(field_name='customer__id') customer_name = filters.CharFilter(field_name='customer__name', lookup_expr='icontains') product_id = filters.NumberFilter(field_name='product__id') product_sku = filters.CharFilter(field_name='product__sku', lookup_expr='exact') class Meta: model = Document fields = ['customer_id', 'customer_name', 'product_id', 'product_sku'] - 把过滤类绑定到ViewSet:
from rest_framework import viewsets from .models import Document from .serializers import DocumentSerializer from .filters import DocumentFilter class DocumentViewSet(viewsets.ModelViewSet): queryset = Document.objects.all() serializer_class = DocumentSerializer filter_class = DocumentFilter - 使用方式:
- 查全量文档:直接访问
/api/documents/ - 按客户ID过滤:
/api/documents/?customer_id=1 - 按产品SKU过滤:
/api/documents/?product_sku=PROD001 - 同时过滤客户和产品:
/api/documents/?customer_id=1&product_id=2
- 查全量文档:直接访问
方案二:自定义get_queryset(无需额外装包)
如果不想引入新依赖,直接重写ViewSet的get_queryset方法手动处理参数:
from rest_framework import viewsets from .models import Document from .serializers import DocumentSerializer class DocumentViewSet(viewsets.ModelViewSet): queryset = Document.objects.all() serializer_class = DocumentSerializer def get_queryset(self): qs = super().get_queryset() # 从请求参数里拿过滤条件 customer_id = self.request.query_params.get('customer_id') product_id = self.request.query_params.get('product_id') customer_name = self.request.query_params.get('customer_name') if customer_id: qs = qs.filter(customer__id=customer_id) if product_id: qs = qs.filter(product__id=product_id) if customer_name: qs = qs.filter(customer__name__icontains=customer_name) return qs
这种方式代码量稍大,但不需要额外依赖,适合简单过滤场景。
两种方案都能在同一个端点实现全量查询和关联过滤,完全不用新增端点。
内容的提问来源于stack exchange,提问作者strumpy_strudel
相关产品推荐
相关产品推荐

