Django模板中实现两个select下拉框选项联动的方法
Django 两级select下拉框联动实现
首先先修正你原有模板的笔误:第二个下拉框循环变量是y,原来写的{{x.instance}}是错误的,要改成{{y.instance}},否则渲染会出问题。
联动根据数据量大小,有两种常用实现方式,按需选择即可:
方案一:前端预加载(适合数据量小的场景,无额外请求)
核心思路是页面渲染时把所有分类对应的实例数据一次性输出到前端,通过JS监听下拉框变化过滤选项。
- 后端视图调整,把实例数据按分类分组后传给模板:
# views.py from django.shortcuts import render def creature_page(request): # 分类列表,替换成你实际的分类查询逻辑 category_list = [{"creature": "animals"}, {"creature": "plants"}] # 所有实例数据,替换成你实际的模型查询,保证每条数据带所属分类字段 all_instances = [ {"instance": "猫", "belong_to": "animals"}, {"instance": "狗", "belong_to": "animals"}, {"instance": "玫瑰", "belong_to": "plants"}, {"instance": "梧桐", "belong_to": "plants"}, ] # 按分类分组 instance_group = {} for item in all_instances: t = item["belong_to"] if t not in instance_group: instance_group[t] = [] instance_group[t].append(item["instance"]) return render(request, "demo.html", { "list": category_list, "instance_group": instance_group })
- 模板代码调整,给实例选项打分类标记,加JS监听逻辑:
<!-- 一级分类下拉框 --> <select id="creatures"> {% for x in list %} <option value="{{x.creature}}">{{x.creature}}</option> {% endfor %} </select> <!-- 二级实例下拉框 --> <select id="instances"> {% for category, instance_names in instance_group.items %} {% for name in instance_names %} <option value="{{name}}" data-category="{{category}}">{{name}}</option> {% endfor %} {% endfor %} </select> <script> const categorySel = document.getElementById('creatures'); const instanceSel = document.getElementById('instances'); // 缓存所有选项 const allOptions = Array.from(instanceSel.options); // 页面初始化先执行一次过滤 filterOptions(); // 监听一级下拉框变化 categorySel.addEventListener('change', filterOptions); function filterOptions() { const currentCategory = categorySel.value; instanceSel.innerHTML = ''; // 过滤匹配分类的选项追加 allOptions.filter(opt => opt.dataset.category === currentCategory) .forEach(opt => instanceSel.add(opt)); } </script>
方案二:AJAX异步加载(适合数据量大的场景,按需拉取数据)
核心思路是二级下拉框的数据不一次性渲染,选中一级分类时,异步请求后端接口拉取对应分类的实例再渲染。
- 后端新增数据查询接口,配置路由:
# views.py 新增接口 from django.http import JsonResponse def get_instance_api(request): category = request.GET.get('category') # 替换成你实际的模型查询逻辑 instances = list(YourInstanceModel.objects.filter(belong_to=category).values_list('instance', flat=True)) return JsonResponse({"data": instances})
# urls.py 加路由 from django.urls import path from . import views urlpatterns = [ path('creature/', views.creature_page, name='creature_page'), path('api/get-instance/', views.get_instance_api, name='get_instance'), ]
- 模板代码调整,加异步请求逻辑:
<select id="creatures"> {% for x in list %} <option value="{{x.creature}}">{{x.creature}}</option> {% endfor %} </select> <select id="instances"> <!-- 初始选项由JS动态加载 --> </select> <script> const categorySel = document.getElementById('creatures'); const instanceSel = document.getElementById('instances'); // 初始化加载 loadInstanceData(); categorySel.addEventListener('change', loadInstanceData); function loadInstanceData() { const currentCategory = categorySel.value; // 请求对应分类的数据 fetch(`/api/get-instance/?category=${currentCategory}`) .then(res => res.json()) .then(res => { instanceSel.innerHTML = ''; res.data.forEach(name => { const opt = document.createElement('option'); opt.value = name; opt.textContent = name; instanceSel.add(opt); }) }) } </script>
注意:如果你的项目开启了CSRF防护,AJAX请求需要带上CSRF令牌,直接参考Django官方文档的CSRF AJAX配置即可。
内容的提问来源于stack exchange,提问作者ahmet yılmaz234
相关产品推荐
相关产品推荐

