You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Django REST framework/django-filter向前端传递可用筛选选项

DRF + django-filter 返回可用筛选选项的最佳实践

这是非常常见的动态筛选场景,目前有两种符合DRF、django-filter规范的实现路径,也有成熟的第三方库可以直接使用:

方案1:直接使用成熟第三方库

你可以直接使用drf-facets这类专门的扩展库,它原生适配django-filter的过滤规则,会自动基于当前已过滤的查询集,统计每个筛选字段的可选值、对应匹配数量,你只需要做简单配置就可以将可用筛选选项注入到API响应中,完全符合框架规范,不用自己手写聚合逻辑。

方案2:自行实现(无额外依赖)

你提到的两种实现思路都是符合DRF设计规范的,可根据业务场景选择:

路径A:自定义Metadata类(OPTIONS请求返回)

这种方案将可用筛选选项作为API元数据返回,和业务数据逻辑分离,适合需要统一管理接口元数据的场景,示例代码如下:

from rest_framework.metadata import BaseMetadata

class FilterOptionsMetadata(BaseMetadata):
    def determine_metadata(self, request, view):
        metadata = super().determine_metadata(request, view)
        # 拿到经过django-filter过滤后的最终查询集
        filtered_queryset = view.filter_queryset(view.get_queryset())
        # 按你的筛选字段配置,统计各字段可用值
        available_filters = {
            "color": list(filtered_queryset.values_list("color", flat=True).distinct()),
            "size": list(filtered_queryset.values_list("size", flat=True).distinct())
        }
        metadata["actions"]["GET"]["available_filters"] = available_filters
        return metadata

使用时只需要在对应视图中指定metadata_class = FilterOptionsMetadata,前端发起OPTIONS请求即可拿到当前查询条件下的可用筛选选项。

路径B:扩展分页响应(GET请求同业务数据返回)

这种方案不需要前端额外发起请求,拉取列表数据的同时就能拿到可用筛选选项,适合高频筛选的交互场景,示例代码如下:

from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

class FilterWithOptionsPagination(PageNumberPagination):
    def get_paginated_response(self, data):
        filtered_queryset = self.page.object_list
        # 统计可用筛选选项
        available_filters = {
            "color": list(filtered_queryset.values_list("color", flat=True).distinct()),
            "size": list(filtered_queryset.values_list("size", flat=True).distinct())
        }
        return Response({
            "count": self.page.paginator.count,
            "next": self.get_next_link(),
            "previous": self.get_previous_link(),
            "available_filters": available_filters,
            "results": data
        })

使用时只需要在对应视图中指定pagination_class = FilterWithOptionsPagination即可。

性能注意事项

如果你的查询集数据量很大,直接对筛选字段做distinct聚合会有明显性能损耗,建议给对应的筛选字段添加数据库索引;如果量级达到百万以上,推荐对接Elasticsearch这类搜索引擎做聚合查询,django-filter支持对接ES查询后端,聚合效率会高很多。


内容的提问来源于stack exchange,提问作者thorsten

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 20:36:08