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

如何在Django通用ListView中实现类似Admin后台的列表筛选功能?

有两种常用的简便实现方案,优先推荐使用django-filter,这是业界通用的实现方式,比照搬Admin内置的筛选逻辑简单很多。


方案1:使用django-filter实现(推荐,代码量最少)

第一步:安装配置

先安装依赖包:
pip install django-filter
之后在项目settings.py的INSTALLED_APPS中添加django_filters即可。

第二步:定义筛选规则

在sales应用下新建filters.py文件,编写筛选类:

import django_filters
from .models import SaleBill

class SaleBillFilter(django_filters.FilterSet):
    # 自定义筛选规则:日期区间筛选
    start_date = django_filters.DateFilter(field_name="time", lookup_expr='gte', label='起始日期')
    end_date = django_filters.DateFilter(field_name="time", lookup_expr='lte', label='结束日期')
    # 客户名模糊搜索
    name = django_filters.CharFilter(lookup_expr='icontains', label='客户姓名')
    
    class Meta:
        model = SaleBill
        # 此处填写你需要的筛选字段,外键、选择型字段会自动生成下拉选择框
        fields = ['billno', 'name', 'start_date', 'end_date']

第三步:修改ListView视图

from django_filters.views import FilterMixin
from .filters import SaleBillFilter

class SaleView(FilterMixin, ListView):
    model = SaleBill
    template_name = "sales/sales_list.html"
    context_object_name = "bills"
    ordering = ["-time"]
    paginate_by = 10
    filterset_class = SaleBillFilter # 绑定自定义筛选类

    def get_queryset(self):
        # 生成经过筛选的查询集
        queryset = self.filterset_class(self.request.GET, queryset=super().get_queryset()).qs
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 将筛选表单传入模板用于渲染
        context['filter'] = self.filterset_class(self.request.GET, queryset=self.get_queryset())
        return context

第四步:修改模板

添加筛选区域

在标题下方、表格上方的位置添加筛选表单:

<div class="card mb-3">
    <div class="card-body">
        <form method="get" class="row g-3">
            {{ filter.form.as_p }}
            <div class="col-auto align-self-end">
                <button type="submit" class="btn btn-primary">筛选</button>
                <a href="{% url '你的销售列表路由名' %}" class="btn btn-outline-secondary">重置</a>
            </div>
        </form>
    </div>
</div>

你已经加载了widget_tweaks标签,可直接用它给表单字段添加自定义样式。

修改分页链接

需要给所有分页链接带上当前筛选参数,避免切换页面时筛选失效,将所有分页的href属性修改为如下格式即可:

href="?{{ filter.form.data.urlencode }}&page=xxx"

例如第一页的链接修改为:
<a class="btn btn-outline-info mb-4" href="?{{ filter.form.data.urlencode }}&page=1">First</a>


方案2:原生Django实现(无需第三方依赖)

如果不想引入额外依赖,可直接重写get_queryset方法实现筛选:

修改视图

class SaleView(ListView):
    model = SaleBill
    template_name = "sales/sales_list.html"
    context_object_name = "bills"
    ordering = ["-time"]
    paginate_by = 10

    def get_queryset(self):
        queryset = super().get_queryset()
        # 从GET请求中获取筛选参数
        name = self.request.GET.get('name')
        start_date = self.request.GET.get('start_date')
        end_date = self.request.GET.get('end_date')
        
        if name:
            queryset = queryset.filter(name__icontains=name)
        if start_date:
            queryset = queryset.filter(time__gte=start_date)
        if end_date:
            queryset = queryset.filter(time__lte=end_date)
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 将当前筛选参数传入模板,用于表单回填
        context['filter_params'] = self.request.GET
        return context

模板添加筛选表单

<div class="card mb-3">
    <div class="card-body">
        <form method="get" class="row g-3">
            <div class="col-auto">
                <label>客户姓名</label>
                <input type="text" name="name" value="{{ filter_params.name|default:'' }}" class="form-control">
            </div>
            <div class="col-auto">
                <label>起始日期</label>
                <input type="date" name="start_date" value="{{ filter_params.start_date|default:'' }}" class="form-control">
            </div>
            <div class="col-auto">
                <label>结束日期</label>
                <input type="date" name="end_date" value="{{ filter_params.end_date|default:'' }}" class="form-control">
            </div>
            <div class="col-auto align-self-end">
                <button type="submit" class="btn btn-primary">筛选</button>
                <a href="{% url '你的销售列表路由名' %}" class="btn btn-outline-secondary">重置</a>
            </div>
        </form>
    </div>
</div>

分页链接同样需要带上筛选参数,格式为:
href="?{{ filter_params.urlencode }}&page=xxx"


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 08:15:03