Django应用中如何用JS实现按选中分类筛选机构
实现分类筛选机构的方案
1. 后端准备关联映射数据
先在视图层生成分类ID与对应机构的映射关系,转成JSON格式传递给前端,避免前端频繁遍历所有机构,提升筛选效率:
# views.py from django.shortcuts import render import json from .models import Category, Institution def step_form(request): categories = Category.objects.all() institutions = Institution.objects.all() # 构建分类ID到机构的映射字典 category_inst_map = {} for inst in institutions: # 假设Institution与Category是多对多关系,字段名为categories for cat in inst.categories.all(): cat_id_str = str(cat.id) if cat_id_str not in category_inst_map: category_inst_map[cat_id_str] = [] category_inst_map[cat_id_str].append({ 'id': str(inst.id), 'name': inst.name # 按需添加其他机构字段 }) # 转义后传递给模板 cat_inst_json = json.dumps(category_inst_map) return render(request, 'step_form.html', { 'categories': categories, 'institutions': institutions, 'cat_inst_json': cat_inst_json })
2. 前端模板与交互逻辑
在分步表单中,给分类选择框绑定事件,根据选中的分类ID筛选并展示对应机构:
<!-- step_form.html --> <!-- 步骤1:分类选择区域 --> <div id="step1" class="form-step"> <h3>选择分类</h3> {% for category in categories %} <label class="category-label"> <input type="checkbox" class="category-checkbox" value="{{ category.id }}"> {{ category.name }} </label> {% endfor %} </div> <!-- 步骤3:机构展示区域 --> <div id="step3" class="form-step"> <h3>选择机构</h3> <div id="institution-list"> <!-- 初始渲染所有机构并隐藏 --> {% for inst in institutions %} <div class="institution-item" data-inst-id="{{ inst.id }}" style="display: none;"> <label> <input type="checkbox" name="selected_institutions" value="{{ inst.id }}"> {{ inst.name }} </label> </div> {% endfor %} </div> </div> <script> // 解析后端传递的分类-机构映射 const categoryInstMap = JSON.parse('{{ cat_inst_json|escapejs }}'); const categoryCheckboxes = document.querySelectorAll('.category-checkbox'); const institutionItems = document.querySelectorAll('.institution-item'); // 核心筛选函数 function filterInstitutions() { // 收集选中的分类ID const selectedCatIds = Array.from(categoryCheckboxes) .filter(cb => cb.checked) .map(cb => cb.value); // 无选中分类时隐藏所有机构 if (selectedCatIds.length === 0) { institutionItems.forEach(item => item.style.display = 'none'); return; } // 收集所有符合条件的机构ID const matchedInstIds = new Set(); selectedCatIds.forEach(catId => { const insts = categoryInstMap[catId] || []; insts.forEach(inst => matchedInstIds.add(inst.id)); }); // 切换机构显示状态 institutionItems.forEach(item => { const instId = item.dataset.instId; item.style.display = matchedInstIds.has(instId) ? 'block' : 'none'; }); } // 给分类复选框绑定变更事件 categoryCheckboxes.forEach(cb => { cb.addEventListener('change', filterInstitutions); }); // 若切换到步骤3时需要触发一次筛选,可在步骤切换函数中调用filterInstitutions() </script>
可选优化点
- 若机构数量庞大,可改为动态生成机构DOM元素:清空
institution-list后,根据匹配的机构ID实时创建元素插入,减少初始DOM体积。 - 添加分类的“全选/全不选”按钮,提升操作效率。
- 若分步表单有步骤切换逻辑,在切换到步骤3时主动调用一次
filterInstitutions(),确保用户能看到最新筛选结果。
内容的提问来源于stack exchange,提问作者Виктор
相关产品推荐
相关产品推荐

