如何在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
相关产品推荐
相关产品推荐

