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

如何在Django ListView中基于用户输入实现动态筛选?

Django ListView 实现多条件物品筛选方案

1. 创建筛选表单

在app目录下新建forms.py,定义对应筛选需求的表单类:

from django import forms
from .models import Item

class ItemFilterForm(forms.Form):
    category = forms.ChoiceField(
        choices=Item.CATEGORY_CHOICES,
        required=False,
        label="分类"
    )
    price_min = forms.DecimalField(
        required=False,
        label="最低价格",
        decimal_places=2,
        max_digits=6
    )
    price_max = forms.DecimalField(
        required=False,
        label="最高价格",
        decimal_places=2,
        max_digits=6
    )
    available = forms.BooleanField(
        required=False,
        label="仅显示可用物品"
    )

2. 修改ListView处理筛选逻辑

重写ListView的get_queryset方法,根据用户提交的GET参数动态过滤数据;同时通过get_context_data将筛选表单传入模板:

from django.views.generic import ListView
from .models import Item
from .forms import ItemFilterForm

class ItemListView(ListView):
    model = Item
    template_name = "items/item_list.html"
    context_object_name = "items"  # 替换默认object_list为更直观的变量名

    def get_queryset(self):
        queryset = super().get_queryset()
        form = ItemFilterForm(self.request.GET)
        
        if form.is_valid():
            # 分类筛选
            category = form.cleaned_data.get("category")
            if category:
                queryset = queryset.filter(category=category)
            
            # 最低价格筛选
            price_min = form.cleaned_data.get("price_min")
            if price_min:
                queryset = queryset.filter(price__gte=price_min)
            
            # 最高价格筛选
            price_max = form.cleaned_data.get("price_max")
            if price_max:
                queryset = queryset.filter(price__lte=price_max)
            
            # 可用性筛选
            available = form.cleaned_data.get("available")
            if available is not None:
                queryset = queryset.filter(available=available)
        
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 传入表单并保留用户已选的筛选条件
        context["filter_form"] = ItemFilterForm(self.request.GET)
        return context

3. 更新模板添加筛选表单

在模板顶部添加筛选表单(使用GET方法提交),同时优化物品列表的显示逻辑:

<!-- 筛选表单 -->
<form method="get" class="filter-form">
    {{ filter_form.as_p }}
    <button type="submit">筛选</button>
    <a href="{% url 'item_list' %}">重置筛选</a>
</form>

<!-- 物品列表 -->
{% for item in items %}
    <div class="item">
        <h2>{{ item.name }}</h2>
        <p>分类: {{ item.get_category_display }}</p>  <!-- 显示分类的友好名称 -->
        <p>价格: {{ item.price }}</p>
        <p>状态: {{ item.available|yesno:"可用,不可用" }}</p>
    </div>
{% empty %}
    <p>没有符合条件的物品</p>
{% endfor %}

补充说明

  • 若需自定义表单样式,可替换{{ filter_form.as_p }}为手动渲染每个字段,方便控制HTML结构。
  • 价格范围筛选支持仅输入最低或最高价格的场景,代码会自动判断参数是否存在再应用筛选。
  • 可用性筛选中使用available is not None,确保用户主动勾选/取消勾选时都能生效,避免默认值干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:42:22