Django工单系统<select>未修改提交空值问题求助
工单编辑页面select字段未修改提交后为空的问题
我用HTML、CSS、JavaScript和Django开发工单系统,实现了字段联动功能,工单创建正常,但编辑环节有问题:未修改<select>字段提交后,该字段会变成空值,修改值则正常。试过设置selected属性、赋值等方法都无效,求解决。
相关代码
verticket.html(表单部分)
<form name="form-ticket" id="formTicket" method="POST" action="{% url 'eticket' ticket.pk %}"> <div class="col-4 mt-4 m-auto"> {% if msg %} <div class="alert {{class}}"> {{msg}} </div> {% endif %} {% csrf_token %} <input class="form-control mt-4" type="text" name="numctt" id="numctt" value="{{ticket.numctt}}" placeholder="{{ticket.numctt}}"> <input class="form-control mt-4" type="text" name="nomctt" id="nomctt" value="{{ticket.nomctt}}" placeholder="{{ticket.nomctt}}"> <select required name="areaserv" id="areaserv"> <option disabled selected hidden>{{ticket.areaserv}}</option> </select> <select required class="followup" name="tiposerv" id="tiposerv"> <option disabled selected hidden >{{ticket.tiposerv}}</option> </select> <input class="form-control mt-4" type="text" name="tickettext" id="tickettext" value="{{ticket.tickettext}}" placeholder="{{ticket.tickettext}}"> {% block usuario %} {% if not request.user.is_staff and ticket.ticketstat == 'Vermelho' %} <input class="btn btn-primary mt-4" type="submit" value="Atualizar"> {% endif %} {% endblock %} </form>
verticket.html(脚本部分)
const first = document.getElementsByName('areaserv')[0]; const second = document.getElementsByName('tiposerv')[0]; const initial = second.innerHTML; const optionMap = { Informática: ['Visita Técnica'], CFTV: ['Instalação', 'Reparo'], Alarmes: ['Instalação', 'Reparo'], Interfones: ['Instalação', 'Reparo'], Telefonia: ['Instalação', 'Reparo'], }; function addOption(selectElement, text) { let option = document.createElement('option'); option.value = text; option.textContent = text; selectElement.append(option); } Object.keys(optionMap).forEach(text => addOption(first, text)); first.addEventListener('change', evt => { second.innerHTML = initial; optionMap[evt.target.value].forEach(text => addOption(second, text)); });
views.py
def verticket(request, pk): ticket = Userdb.objects.get(pk = pk) context = {'ticket': ticket} return render(request,'dashboard/verticket.html', context)
解决方案
问题核心:当前<select>初始只有一个disabled的选项,虽然显示了工单原有值,但disabled属性会让表单忽略该值;同时JS初始化时仅添加了areaserv的选项,未将原有值设置为选中状态,导致未修改时表单无有效选中值提交。
方案1:通过Django模板生成有效选项并设置选中
- 注册Django自定义过滤器,用于模板中字典取值:
在app的templatetags目录下创建custom_filters.py:
from django import template register = template.Library() @register.filter def get_item(dictionary, key): return dictionary.get(key)
- 修改模板中的select部分:
{% load custom_filters %} <select required name="areaserv" id="areaserv"> {% for area in optionMap.keys %} <option value="{{area}}" {% if area == ticket.areaserv %}selected{% endif %}>{{area}}</option> {% endfor %} </select> <select required class="followup" name="tiposerv" id="tiposerv"> {% for tipo in optionMap|get_item:ticket.areaserv %} <option value="{{tipo}}" {% if tipo == ticket.tiposerv %}selected{% endif %}>{{tipo}}</option> {% endfor %} </select>
注意:需将
optionMap字典传入模板context,修改views.py:
def verticket(request, pk): ticket = Userdb.objects.get(pk = pk) option_map = { 'Informática': ['Visita Técnica'], 'CFTV': ['Instalação', 'Reparo'], 'Alarmes': ['Instalação', 'Reparo'], 'Interfones': ['Instalação', 'Reparo'], 'Telefonia': ['Instalação', 'Reparo'], } context = {'ticket': ticket, 'optionMap': option_map} return render(request,'dashboard/verticket.html', context)
- 调整JS逻辑,无需再手动添加
areaserv选项:
const first = document.getElementsByName('areaserv')[0]; const second = document.getElementsByName('tiposerv')[0]; const optionMap = { Informática: ['Visita Técnica'], CFTV: ['Instalação', 'Reparo'], Alarmes: ['Instalação', 'Reparo'], Interfones: ['Instalação', 'Reparo'], Telefonia: ['Instalação', 'Reparo'], }; first.addEventListener('change', evt => { second.innerHTML = ''; optionMap[evt.target.value].forEach(text => { let option = document.createElement('option'); option.value = text; option.textContent = text; second.append(option); }); });
方案2:纯JS初始化选项并设置选中
修改HTML的select为空白:
<select required name="areaserv" id="areaserv"></select> <select required class="followup" name="tiposerv" id="tiposerv"></select>
调整JS代码,加载时添加所有选项并标记选中:
const first = document.getElementsByName('areaserv')[0]; const second = document.getElementsByName('tiposerv')[0]; const optionMap = { Informática: ['Visita Técnica'], CFTV: ['Instalação', 'Reparo'], Alarmes: ['Instalação', 'Reparo'], Interfones: ['Instalação', 'Reparo'], Telefonia: ['Instalação', 'Reparo'], }; // 从模板获取初始值 const initialArea = '{{ticket.areaserv}}'; const initialTipo = '{{ticket.tiposerv}}'; function addOption(selectElement, text, isSelected) { let option = document.createElement('option'); option.value = text; option.textContent = text; if (isSelected) option.selected = true; selectElement.append(option); } // 初始化areaserv选项 Object.keys(optionMap).forEach(text => { addOption(first, text, text === initialArea); }); // 初始化tiposerv选项 optionMap[initialArea].forEach(text => { addOption(second, text, text === initialTipo); }); first.addEventListener('change', evt => { second.innerHTML = ''; optionMap[evt.target.value].forEach(text => addOption(second, text)); });
两种方案都能保证初始时select有有效的选中选项,未修改时表单会提交原有值,不会出现空值问题。
内容的提问来源于stack exchange,提问作者Yukki
相关产品推荐
相关产品推荐

