在Django中实现无需提交按钮的下拉框值实时更新
实现Django下拉选择自动同步数据库(无需更新按钮)
要实现用户切换KPI下拉选项后自动同步到数据库,需要结合后端API视图、模板数据绑定和前端AJAX请求三部分完成,具体步骤如下:
1. 后端添加KPI更新视图
在views.py中新增处理POST请求的视图,接收前端传来的Usecase ID和KPI ID,更新数据库中的外键关联:
from django.http import JsonResponse from django.views.decorators.http import require_POST @user_login_required @require_POST def update_usecase_kpi(request): usecase_id = request.POST.get('usecase_id') kpi_id = request.POST.get('kpi_id') try: usecase = Usecase.objects.get(usecase_id=usecase_id) kpi = Kpi.objects.get(id=kpi_id) usecase.kpi = kpi usecase.save() return JsonResponse({'status': 'success', 'kpi_name': kpi.kpi_name}) except (Usecase.DoesNotExist, Kpi.DoesNotExist): return JsonResponse({'status': 'error', 'message': '数据不存在'}, status=404)
在urls.py中添加对应路由:
path('usecase/<str:ucid>/update-kpi/', views.update_usecase_kpi, name='update_usecase_kpi'),
2. 修改模板,添加数据标识和事件绑定
更新模板下拉列表部分,给每个选项绑定KPI ID,标记当前Usecase的ID,方便前端获取数据:
{% if usecase_details is not none and usecase_details %} <div class="card card-body shadow-sm mb-4 mb-lg-0"> {% for result in usecase_details %} <!-- 省略其他代码 --> <ul class="list-group list-group-flush"> <li class="list-group-item d-flex align-items-center justify-content-between px-0 border-bottom"> <div class="btn-group"> <!-- 给显示当前KPI的按钮加唯一ID,方便后续更新文本 --> <button type="button" class="btn btn-secondary" id="current-kpi-{{ result.usecase_id }}"> KPI: {{ result.kpi.kpi_name }} </button> <button type="button" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"> <svg class="icon icon-xs" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg> </button> <ul class="dropdown-menu"> {% for kpi in uckpi %} <!-- 添加data属性存储关键数据,绑定点击事件 --> <li> <a class="dropdown-item" data-usecase-id="{{ result.usecase_id }}" data-kpi-id="{{ kpi.id }}" data-kpi-name="{{ kpi.kpi_name }}"> {{ kpi.kpi_name }} </a> </li> {% endfor %} </ul> </div> </li> </ul> {% endfor %} </div> {% endif %} <!-- 引入Django CSRF令牌,AJAX POST请求必须携带 --> {% csrf_token %}
3. 添加前端AJAX逻辑
在模板底部添加JS代码,监听下拉选项点击事件,发送请求更新数据库并同步页面显示:
<script> // 获取CSRF令牌 const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value; // 事件委托监听下拉选项点击 document.addEventListener('click', function(e) { if (e.target.classList.contains('dropdown-item')) { const usecaseId = e.target.dataset.usecaseId; const kpiId = e.target.dataset.kpiId; const kpiName = e.target.dataset.kpiName; // 发送POST请求到后端更新接口 fetch(`/usecase/${usecaseId}/update-kpi/`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRFToken': csrftoken }, body: `usecase_id=${usecaseId}&kpi_id=${kpiId}` }) .then(response => response.json()) .then(data => { if (data.status === 'success') { // 更新页面上的KPI显示文本 document.getElementById(`current-kpi-${usecaseId}`).textContent = `KPI: ${data.kpi_name}`; // 关闭下拉菜单 const dropdown = new bootstrap.Dropdown(e.target.closest('.btn-group')); dropdown.hide(); } else { alert('更新失败:' + data.message); } }) .catch(error => { console.error('请求出错:', error); alert('更新失败,请稍后重试'); }); } }); </script>
关键说明
- CSRF令牌:Django默认启用CSRF保护,AJAX POST请求必须携带
X-CSRFToken头,否则会被拒绝。 - 事件委托:使用
document.addEventListener监听点击,避免动态生成的下拉项无法绑定事件的问题。 - 错误处理:前后端都添加了错误捕获,确保更新失败时能给出明确提示。
内容的提问来源于stack exchange,提问作者JHS99
相关产品推荐
相关产品推荐

