如何使用django-filter基于反向外键字段实现筛选功能?
解决Django ListAPIView中跨关联模型字段筛选的问题
嘿,我明白你现在的需求——想通过关联模型TDebtData里的agr_num字段来筛选TDebtor实例对吧?默认的filterset_fields只能处理当前模型的字段,所以咱们得自定义一个FilterSet来实现跨表筛选。下面是具体的步骤:
1. 准备工作(确保依赖已安装)
首先确认你已经安装了django-filter,如果还没装,先执行:
pip install django-filter
然后在你的views文件里导入必要的模块:
from django_filters import FilterSet, CharFilter from .models import TDebtor, TDebtData from rest_framework import generics
2. 自定义FilterSet类
创建一个继承自FilterSet的类,专门处理TDebtor的筛选逻辑,添加针对agr_num的跨表筛选规则:
class TDebtorFilter(FilterSet): # 定义agr_num筛选字段,通过双下划线关联到关联模型的字段 # lookup_expr可选'exact'(精确匹配)或'icontains'(模糊匹配),按需调整 agr_num = CharFilter(field_name='debtor_debt_data__agr_num', lookup_expr='exact') class Meta: model = TDebtor # 保留原有的TDebtor自身字段筛选,同时加入新的agr_num fields = ['iin', 'first_name', 'surname', 'middle_name', 'birth_date', 'alive', 'agr_num']
3. 修改你的ListAPIView
把原来的filterset_fields替换成自定义的filterset_class,另外注意你原来代码里的for i in queryset:放在类定义里是错误的(类初始化阶段queryset还未执行,会导致不必要的循环),建议移除这段调试代码。修改后的View如下:
class ProductList(generics.ListAPIView): # 优化预取逻辑:不需要在Prefetch里再加select_related('id_debtor'),因为已经从TDebtor侧预取关联数据 queryset = TDebtor.objects.prefetch_related('debtor_debt_data') serializer_class = TDebtorSerializer filter_backends = [DjangoFilterBackend] # 使用自定义的FilterSet替代默认字段配置 filterset_class = TDebtorFilter
原理说明
- Django的双下划线
__语法支持跨模型关联字段的查询,debtor_debt_data__agr_num表示通过TDebtor的反向关联debtor_debt_data,找到对应TDebtData实例的agr_num字段。 - 自定义FilterSet可以突破默认
filterset_fields的限制,让我们轻松实现关联模型字段的筛选逻辑。
现在你就可以通过传入agr_num=1238HFD32这样的参数,筛选出拥有对应债务编号的债务人实例了!
内容的提问来源于stack exchange,提问作者Azat




