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

Django循环生成下拉菜单时如何设置唯一ID?

解决Django循环渲染表单时下拉框ID重复的问题

方案一:模板手动渲染字段,自定义唯一ID

直接拆分表单字段,结合incident.id(或forloop.counter)生成唯一ID,这是最直接的调整方式:

修改模板代码:

{% for incident in all_incidents %} 
    <select name="status_{{ incident.id }}" required id="id_status_{{ incident.id }}">
        <option value="" selected>Select a Status</option>
        {% for choice in test_status.status.field.choices %}
            <option value="{{ choice.0 }}">{{ choice.1 }}</option>
        {% endfor %}
    </select>
{% endfor %}

优先用incident.id而非forloop.counter,因为数据库ID是Incident的唯一标识,不会因列表排序变动而错位。提交后可在视图中通过request.POST.get(f'status_{incident.id}')获取对应Incident的状态值。

方案二:用表单集(Formset)生成天然唯一的字段

表单集自动为每个表单字段添加索引前缀,既能保证ID唯一,也能规范处理提交数据:

1. 调整表单与视图代码

先创建关联Incident的普通表单,再生成对应数量的表单集:
forms.py

from django import forms
from .models import IncidentStatus

class IncidentStatusForm(forms.Form):
    status = forms.ModelChoiceField(
        queryset=IncidentStatus.objects.all().order_by('status'),
        empty_label='Select a Status',
        label=''
    )
    incident_id = forms.IntegerField(widget=forms.HiddenInput())

views.py

from django.forms import formset_factory
from .forms import IncidentStatusForm

def set_status(req):
    all_incidents = Incident.objects.all()
    # 生成与Incident数量匹配的表单集
    StatusFormSet = formset_factory(IncidentStatusForm, extra=len(all_incidents))
    
    if req.method == 'POST':
        formset = StatusFormSet(req.POST)
        if formset.is_valid():
            for form in formset:
                incident_id = form.cleaned_data.get('incident_id')
                status = form.cleaned_data.get('status')
                # 执行更新Incident状态的逻辑
                incident = Incident.objects.get(id=incident_id)
                incident.status = status
                incident.save()
    else:
        # 初始化表单集,填入对应Incident的ID
        formset = StatusFormSet(initial=[{'incident_id': inc.id} for inc in all_incidents])
    
    context = {'formset': formset, 'all_incidents': all_incidents}
    return render(req, 'incident_main/assignee.html', context)

2. 调整模板代码

{% for form in formset %}
    {{ form.incident_id }}
    {{ form.status }}
    <!-- 自动生成的ID格式:id_form-0-status、id_form-1-status... 天然唯一 -->
{% endfor %}

原方法失效原因

  • 重复渲染同一个表单实例:Django表单的ID是实例生成时固定的,循环渲染同一个test_status只会输出相同ID。
  • 未手动渲染字段:直接用{{ test_status }}渲染整表单时,模板变量无法修改已生成的HTML元素ID,必须拆分字段自定义。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:30:56