如何实现django-filter中过滤器的联动依赖功能
Django-Filter 实现过滤器依赖联动
以下示例以「选择交易对手(CounterParty)后,仅显示该交易对手关联的对象(ObjectList)」为例,你可以根据自己的业务字段(比如name和car)调整对应逻辑。
后端动态调整过滤器QuerySet
核心思路是在FilterSet初始化时,根据已提交的过滤参数,动态修改关联过滤器的可选范围。修改你的filters.py如下:
import django_filters from django.db.models import Q from common.filters import CustomDateRangeWidget from common.models import CounterParty, ObjectList from .models import OpenPointList class OpenPointFilter(django_filters.FilterSet): """ 用于按日期、交易对手名称和对象名称过滤OpenPointList模型的Django-filter类 """ CHOICES = ( ('Closed', '已关闭'), ('Open', '已开启') ) status = django_filters.ChoiceFilter(choices=CHOICES) # 添加交易对手过滤器 counter_party = django_filters.ModelChoiceFilter( label='交易对手', queryset=CounterParty.objects.all() ) # 初始化时先不指定对象过滤器的queryset,后续动态赋值 open_point_object = django_filters.ModelChoiceFilter( label='关联对象', queryset=ObjectList.objects.none() ) category_choice = django_filters.ModelChoiceFilter( label='分类', queryset=OpenPointList.objects.values_list('category', flat=True).distinct() ) category = django_filters.CharFilter(method='custom_category_filter') class Meta: model = OpenPointList fields = ( 'counter_party', 'open_point_object', 'status', 'category', ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 获取请求中已选择的交易对手ID counter_party_id = self.data.get('counter_party') if counter_party_id: # 更新对象过滤器的可选范围,仅显示该交易对手关联的对象 self.filters['open_point_object'].queryset = ObjectList.objects.filter( counter_party_id=counter_party_id ) else: # 未选择交易对手时,显示所有对象 self.filters['open_point_object'].queryset = ObjectList.objects.all()
前端AJAX联动更新下拉选项
后端调整后,需要前端监听第一个过滤器的变化,实时请求更新第二个过滤器的选项。在你的模板中添加以下代码:
<!-- 表单渲染完成后添加 --> <script> document.addEventListener('DOMContentLoaded', function() { // 获取交易对手下拉框(ID根据实际表单渲染结果调整) const counterPartySelect = document.getElementById('id_counter_party'); // 获取关联对象下拉框 const objectSelect = document.getElementById('id_open_point_object'); counterPartySelect.addEventListener('change', function() { const counterPartyId = this.value; // 发送AJAX请求获取对应对象列表 fetch(`/get_objects/?counter_party_id=${counterPartyId}`) .then(response => response.json()) .then(data => { // 清空现有选项 objectSelect.innerHTML = '<option value="">---------</option>'; // 追加新选项(假设ObjectList模型有name字段用于显示) data.forEach(obj => { const option = document.createElement('option'); option.value = obj.id; option.textContent = obj.name; objectSelect.appendChild(option); }); }); }); }); </script>
配套视图与路由
在views.py中添加返回JSON数据的视图:
from django.http import JsonResponse from common.models import ObjectList def get_objects(request): counter_party_id = request.GET.get('counter_party_id') objects = [] if counter_party_id: # 仅返回需要的字段(ID和显示名称) objects = ObjectList.objects.filter(counter_party_id=counter_party_id).values('id', 'name') return JsonResponse(list(objects), safe=False)
在urls.py中添加对应路由:
from django.urls import path from .views import get_objects urlpatterns = [ # 其他现有路由... path('get_objects/', get_objects, name='get_objects'), ]
内容的提问来源于stack exchange,提问作者Zesshi
相关产品推荐
相关产品推荐

