You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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模板生成有效选项并设置选中

  1. 注册Django自定义过滤器,用于模板中字典取值:
    在app的templatetags目录下创建custom_filters.py:
from django import template

register = template.Library()

@register.filter
def get_item(dictionary, key):
    return dictionary.get(key)
  1. 修改模板中的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)
  1. 调整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:44:53