如何通过Django Filter Backend URL参数过滤外键关联多模型
解决Django Filter Backend同时过滤关联模型字段的方法
要同时过滤Master和MasterDetail两个模型的字段,核心是基于MasterDetail模型创建FilterSet,通过双下划线__跨表关联Master的字段,同时处理自身的字段。具体步骤如下:
1. 自定义MasterDetailFilter类
创建继承自django_filters.FilterSet的过滤类,明确指定过滤的字段(包括跨表关联的Master字段和MasterDetail自身字段):
import django_filters from .models import MasterDetail class MasterDetailFilter(django_filters.FilterSet): # 关联Master→Company的company_code字段,对应URL参数company_code company_code = django_filters.CharFilter( field_name='master__company__company_code', lookup_expr='exact' # 按需改为icontains实现模糊匹配 ) # 关联MasterDetail自身的recordtypes字段,假设RecordTypes模型用name匹配URL参数recordtypes recordtypes = django_filters.CharFilter( field_name='recordtypes__name', lookup_expr='exact' ) class Meta: model = MasterDetail fields = ['company_code', 'recordtypes'] # 暴露的过滤参数名
2. 修改视图配置
将视图的filterset_class替换为上面的MasterDetailFilter,同时调整queryset和search_fields为MasterDetail相关的路径:
from rest_framework import generics, filters from django_filters.rest_framework import DjangoFilterBackend from .models import MasterDetail from .serializers import masterDetailAllSerializer from .pagination import StandardResultsSetPagination class masterListAllView(generics.ListAPIView): # 搜索字段也需要改为跨表路径 search_fields = ['master__company__company_code'] filter_backends = [DjangoFilterBackend, filters.SearchFilter] filterset_class = MasterDetailFilter # 替换为新的过滤类 serializer_class = masterDetailAllSerializer pagination_class = StandardResultsSetPagination # 明确指定queryset为MasterDetail,并用select_related优化关联查询 queryset = MasterDetail.objects.select_related( 'master', 'master__company', 'recordtypes' ).all()
关键说明
- 跨表过滤规则:Django ORM中用双下划线
__实现跨外键关联,比如master__company__company_code表示从MasterDetail关联到Master,再从Master关联到Company,最终取Company的company_code字段。 - 字段匹配调整:如果URL参数
recordtypes对应的是RecordTypes模型的code字段而非name,只需把field_name改为recordtypes__code即可。 - 性能优化:使用
select_related提前加载关联模型数据,避免多次数据库查询导致的性能问题。
内容的提问来源于stack exchange,提问作者uyarc
相关产品推荐
相关产品推荐

