如何获取Django中Bootstrap form-select选中值并更新员工表?
解决Django中Bootstrap下拉框选中值过滤员工表的问题
第一步:修正下拉框的value绑定错误
你当前的下拉框选项value写死成了字符串"restaurant.name",这会导致选中后无法获取正确的餐厅标识。改成绑定餐厅的唯一ID(推荐,避免名称重复)或者名称:
<div class="div-1 rounded bg-light text-dark "> {% trans "Active restaurant: " %} <!-- 方案一:用表单提交的话,包裹form标签 --> <form method="GET" action=""> <select class="form-select-sm bg-light text-dark" aria-label="{% trans 'Select a restaurant' %}" id="Selected_Restaurant" name="restaurant_id"> <option value="">{% trans "Select a restaurant" %}</option> {% for restaurant in restaurants %} <!-- 绑定餐厅ID作为value,后端更易处理 --> <option value="{{ restaurant.id }}" {% if request.GET.restaurant_id == restaurant.id|stringformat:"i" %}selected{% endif %}>{{ restaurant.name }}</option> {% endfor %} </select> <!-- 可选:添加提交按钮,或者用JS自动提交 --> <button type="submit" class="btn btn-sm btn-outline-primary mt-2">{% trans "Filter" %}</button> </form> </div>
方案一:页面刷新式过滤(后端处理)
这种方式简单直接,适合不需要无刷新的场景:
- 修改视图函数:在渲染home页面的视图中,获取前端传递的餐厅ID,过滤员工数据
from django.shortcuts import render from .models import Restaurant, Employee def home(request): restaurants = Restaurant.objects.all() # 获取选中的餐厅ID restaurant_id = request.GET.get('restaurant_id') if restaurant_id: # 过滤属于该餐厅的员工 employees = Employee.objects.filter(restaurant_id=restaurant_id) else: # 默认显示所有员工,或者空 employees = Employee.objects.all() context = { 'restaurants': restaurants, 'employees': employees, } return render(request, 'home.html', context)
- 修改员工表模板:去掉硬编码的判断条件,直接渲染过滤后的员工:
<table class="table table-sm table-hover"> <thead class="table-success"> <tr> <th scope="col">{% trans "Restaurant" %}</th> <th scope="col">{% trans "First name" %}</th> <th scope="col">{% trans "Last name" %}</th> <th scope="col">{% trans "Username" %}</th> </tr> </thead> <tbody class="table-group-divider"> {% for employee in employees %} <tr> <td>{{ employee.restaurant.name }}</td> <td>{{ employee.user.first_name }}</td> <td>{{ employee.user.last_name }}</td> <td>{{ employee.user.username }}</td> </tr> {% empty %} <tr> <td colspan="4" class="text-center">{% trans "No employees found for this restaurant" %}</td> </tr> {% endfor %} </tbody> </table>
方案二:无刷新AJAX过滤(用户体验更好)
如果希望选中下拉框后自动更新表格,不用刷新页面,用JS实现:
- 修改下拉框(不需要form标签):
<div class="div-1 rounded bg-light text-dark "> {% trans "Active restaurant: " %} <select class="form-select-sm bg-light text-dark" aria-label="{% trans 'Select a restaurant' %}" id="Selected_Restaurant"> <option value="">{% trans "Select a restaurant" %}</option> {% for restaurant in restaurants %} <option value="{{ restaurant.id }}">{{ restaurant.name }}</option> {% endfor %} </select> </div>
- 添加AJAX脚本:放在模板底部,监听下拉框的change事件,请求后端接口获取过滤后的员工HTML:
<script> document.getElementById('Selected_Restaurant').addEventListener('change', function() { const restaurantId = this.value; const tableBody = document.querySelector('.table-group-divider'); // 发送AJAX请求 fetch(`{% url 'filter_employees' %}?restaurant_id=${restaurantId}`) .then(response => response.text()) .then(html => { tableBody.innerHTML = html; }) .catch(error => console.error('Error fetching employees:', error)); }); </script>
- 添加后端接口视图:创建一个专门返回员工表格内容的视图:
from django.http import HttpResponse from django.shortcuts import render def filter_employees(request): restaurant_id = request.GET.get('restaurant_id') if restaurant_id: employees = Employee.objects.filter(restaurant_id=restaurant_id) else: employees = Employee.objects.all() # 渲染表格body的片段 return render(request, 'employee_table_body.html', {'employees': employees})
- 创建表格片段模板
employee_table_body.html:
{% for employee in employees %} <tr> <td>{{ employee.restaurant.name }}</td> <td>{{ employee.user.first_name }}</td> <td>{{ employee.user.last_name }}</td> <td>{{ employee.user.username }}</td> </tr> {% empty %} <tr> <td colspan="4" class="text-center">{% trans "No employees found for this restaurant" %}</td> </tr> {% endfor %}
- 配置URL:在urls.py中添加接口路由:
from django.urls import path from . import views urlpatterns = [ path('', views.home, name='home'), path('filter-employees/', views.filter_employees, name='filter_employees'), ]
关键注意点
- 推荐用餐厅ID作为value,而不是名称,因为名称可能重复,导致过滤错误
- 如果用名称作为value,视图中要改成
Employee.objects.filter(restaurant__name=restaurant_name),但要注意名称的唯一性 - AJAX方式如果用POST请求,需要处理CSRF令牌,GET请求无需额外处理
内容的提问来源于stack exchange,提问作者Olav Lindkjolen
相关产品推荐
相关产品推荐

