如何在Django3.2中实现无需提交按钮、支持AJAX的多选复选框过滤功能
Django 复选框多选联动AJAX无刷新筛选实现方案
开发环境:Python 3.9 + Django 3.2
1. 前端模板修改
首先调整原有表单,移除提交按钮,新增产品列表渲染容器用于动态更新筛选结果:
<form method="post" id="category-box"> {% csrf_token %} {% for c in category_list %} <div class="form-check"> <input class="form-check-input" type="checkbox" name="category" value="{{c.name}}" id="{{c.name}}"> <label class="form-check-label" for="{{c.name}}"> <a href="{{ c.get_absolute_url }}">{{ c.name }}</a> </label> </div> {% endfor %} </form> <!-- 动态更新的产品列表容器 --> <div id="product-list-container"> {% include "product_list_partial.html" %} </div>
相比缓存参数追加的方案,后续采用每次全量收集已选值的逻辑,更简洁且能兼容用户取消勾选的操作,避免参数缓存错乱
2. JS交互逻辑实现
用原生JS实现复选框事件监听、参数收集和AJAX请求:
// 初始化DOM元素 const checkboxes = document.querySelectorAll('input[name="category"]'); const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; const productContainer = document.getElementById('product-list-container'); // 给所有复选框绑定选中变化事件 checkboxes.forEach(checkbox => { checkbox.addEventListener('change', function() { // 全量收集所有已勾选的分类值 const selectedCategories = Array.from(checkboxes) .filter(item => item.checked) .map(item => item.value); // 发送筛选请求 fetch(window.location.href, { method: 'POST', headers: { 'X-CSRFToken': csrfToken, 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' // 标记为AJAX请求,方便后端识别 }, body: `category=${encodeURIComponent(JSON.stringify(selectedCategories))}` }) .then(res => res.text()) .then(html => { // 替换页面产品列表内容 productContainer.innerHTML = html; }) .catch(err => console.error('筛选请求失败:', err)); }); });
3. 后端视图逻辑调整
修改原产品列表视图,识别AJAX请求时返回局部模板内容:
from django.shortcuts import render from .models import Product, Category import json def product_list(request): products = Product.objects.all() categories = Category.objects.all() # 处理AJAX筛选请求 if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest': if request.POST.get('category'): selected_cats = json.loads(request.POST.get('category')) if selected_cats: # 按选中的分类筛选产品 products = products.filter(category__name__in=selected_cats) # 仅返回产品列表的局部HTML return render(request, 'product_list_partial.html', {'products': products}) # 普通页面请求返回完整页面 return render(request, 'product_list.html', { 'products': products, 'category_list': categories })
4. 新增产品列表局部模板
新建product_list_partial.html,仅编写产品列表渲染代码即可:
{% for product in products %} <div class="product-item"> <h3>{{ product.name }}</h3> <p>分类:{{ product.category.name }}</p> <p>价格:¥{{ product.price }}</p> <!-- 其他产品自定义字段 --> </div> {% empty %} <p>暂无符合筛选条件的产品</p> {% endfor %}
注意事项
- 局部模板不要包含页面头尾、公共CSS/JS等内容,仅保留产品列表本身的HTML结构
- 如果需要扩展价格、销量等其他筛选条件,只需在JS收集参数时新增对应字段取值,后端同步补充筛选逻辑即可
- 未勾选任何分类时默认返回全部产品,可根据业务需求调整该逻辑
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

