Django如何在view中访问filter筛选数据供模板展示筛选条件
Django视图访问表单筛选条件并传递给模板的最佳实践
核心原则:永远不要直接把原始请求参数透传给模板,所有筛选参数统一在视图层完成校验、清洗后,以结构化数据的形式传入模板上下文,避免模板层处理冗余逻辑、也规避未校验参数带来的安全问题。
根据你用的筛选实现方案,对应处理方式如下:
如果你用
django-filter(绝大多数列表页筛选场景的标准选型)
实例化FilterSet后,直接取校验通过的清洗数据即可,这部分数据已经自动完成了类型转换、非法值过滤,你只需要剔除空值就能拿到当前所有生效的筛选条件:def demo_list_view(request): from .filters import DemoModelFilter from .models import DemoModel filter_set = DemoModelFilter(request.GET, queryset=DemoModel.objects.all()) # 过滤掉未传、值为空的无效筛选项 active_filters = {} for field_name, value in filter_set.form.cleaned_data.items(): if value not in [None, "", []]: active_filters[field_name] = value context = { "filter": filter_set, "active_filters": active_filters, "object_list": filter_set.qs } return render(request, "demo_list.html", context)模板里直接遍历
active_filters就能展示所有当前生效的筛选条件,不需要额外做判空、类型处理。如果你是手写筛选逻辑、没有用第三方筛选库
先在视图里定义好允许作为筛选条件的字段白名单,逐个校验参数合法性、执行筛选逻辑的同时,把有效参数收集起来传入上下文,绝对不要直接把整个request.GET丢给模板遍历:def demo_list_view(request): from .models import DemoModel qs = DemoModel.objects.all() active_filters = {} status = request.GET.get("status") if status and status.isdigit(): qs = qs.filter(status=status) active_filters["状态"] = dict(DemoModel.STATUS_CHOICES).get(int(status), status) category = request.GET.get("category") if category: qs = qs.filter(category__name=category) active_filters["分类"] = category publish_year = request.GET.get("publish_year") if publish_year and publish_year.isdigit() and len(publish_year) ==4: qs = qs.filter(publish_time__year=publish_year) active_filters["发布年份"] = publish_year context = { "active_filters": active_filters, "object_list": qs } return render(request, "demo_list.html", context)
避坑提醒:不要图省事直接在模板里遍历
request.GET拿筛选参数,一是会带上分页参数、随机传入的无效参数,二是拿到的都是原始字符串,像choices字段、外键字段没法直接展示用户可读的文本,三是未经过滤的参数直接渲染存在XSS安全隐患。
如果需要展示筛选项的可读名称、值的对应文本,统一在视图层完成映射处理,不要在模板里写大量分支判断。
内容的提问来源于stack exchange,提问作者paralosreg
相关产品推荐
相关产品推荐

