如何在DRF FilterSet中使用django-clever-selects实现联动筛选
你之前的概念代码无法运行的核心原因是:django-filter的ChoiceFilter不会自动传递parent_field、ajax_url这类非标准参数给底层自定义字段,且django-clever-selects的ChainedChoiceField依赖配套的前端逻辑才能实现联动效果,完整的实现方案如下:
后端实现
首先自定义联动筛选器类,重写初始化方法透传联动参数给底层字段:
from django_filters.rest_framework import filters from django_filters.rest_framework.filterset import FilterSet from clever_selects.form_fields import ChainedChoiceField from django.utils.translation import gettext_lazy as _ from django.urls import reverse_lazy class ChainedChoiceFilter(filters.ChoiceFilter): def __init__(self, *args, **kwargs): # 提取ChainedChoiceField需要的专属参数,避免传给父类 self.parent_field = kwargs.pop('parent_field', None) self.ajax_url = kwargs.pop('ajax_url', None) super().__init__(*args, **kwargs) # 手动实例化联动字段并传入所有配置 self.field = ChainedChoiceField( label=self.label, parent_field=self.parent_field, ajax_url=self.ajax_url, required=self.extra.get('required', False), choices=self.choices or [('', '---------')] ) # 业务FilterSet直接使用自定义筛选器即可 class SomeFilterSet(FilterSet): # 先定义父级筛选字段 some_parent_field = filters.ChoiceFilter(choices=你的父字段选项列表) # 定义联动子字段 some_field = ChainedChoiceFilter( label=_("依赖父字段的联动筛选字段"), parent_field="some_parent_field", ajax_url=reverse_lazy('ajax:AjaxSomeView') )
原有给表单提供选项的Ajax接口可以直接复用,不需要修改,只要确保接口接收的父字段参数名和parent_field配置的值一致即可。
前端适配
不同场景下需要手动引入django-clever-selects的前端逻辑才能触发联动效果:
- 如果你使用django-filter自带的服务端渲染筛选页面,直接在页面模板中引入配套静态资源即可:
<script type="text/javascript" src="{% static 'clever_selects/js/jquery.chained.min.js' %}"></script> <script type="text/javascript" src="{% static 'clever_selects/js/clever_selects.js' %}"></script>
- 如果你是前后端分离项目,自行实现前端筛选表单,只需要监听父字段的值变化事件,调用对应Ajax接口获取子字段选项列表,替换子字段的下拉选项即可,逻辑和django-clever-selects的默认JS逻辑完全一致。
注意:DRF自动生成的OpenAPI接口文档不会自动体现联动筛选的依赖关系,需要手动在文档中补充说明字段关联规则。
内容的提问来源于stack exchange,提问作者Johannes Pertl
相关产品推荐
相关产品推荐

