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

Django创建投票时如何实现可动态添加任意数量Choice ModelForm表单

实现动态新增投票选项的方案

你需要借助Django的Formset功能处理多组Choice表单提交,配合前端JS实现动态新增入口,总共分三步修改:

第一步:修改forms.py,创建选项表单集

我们用formset_factory生成可批量提交的Choice表单集合:

from django import forms
from django.forms import formset_factory
from .models import Question, Choice

class NewPollForm(forms.ModelForm):
    class Meta:
        model = Question
        labels = { 
            "questionText":"投票问题"
        }
        fields = ("questionText",)

class NewChoicesForm(forms.ModelForm):
    class Meta:
        model = Choice
        labels = {
            "choiceText":"选项内容"
        }
        fields = ("choiceText",)

# 创建选项表单集,默认初始显示2个选项,允许提交时动态新增
ChoiceFormSet = formset_factory(
    NewChoicesForm,
    extra=2, # 初始显示的空选项数量
    can_delete=False, # 不需要删除功能可以设为False
    min_num=2, # 最少需要填2个选项
    validate_min=True
)

第二步:修改视图函数,处理表单集提交

需要调整原视图逻辑,批量保存所有提交的选项:

from django.shortcuts import render, redirect
from django.utils import timezone
from .forms import NewPollForm, ChoiceFormSet

def newpoll(request):
    if not request.user.is_authenticated:
        return redirect("users:signup")
    if request.method == "POST":
        qform = NewPollForm(request.POST)
        # 用POST数据初始化表单集
        choice_formset = ChoiceFormSet(request.POST)
        if qform.is_valid() and choice_formset.is_valid():
            # 先保存问题
            newpoll = qform.save(commit=False)
            newpoll.user = request.user
            newpoll.save()
            # 批量保存所有选项
            for form in choice_formset:
                # 跳过用户没填的空选项
                if form.cleaned_data.get('choiceText'):
                    choice = form.save(commit=False)
                    choice.question = newpoll
                    choice.save()
            return redirect("polls:details", pollid=newpoll.pk)
    else:
        qform = NewPollForm()
        choice_formset = ChoiceFormSet()
    return render(request, "polls/newpoll.html", {"qform": qform, "choice_formset": choice_formset})

第三步:修改模板newpoll.html,添加动态新增按钮

需要先渲染表单集的管理字段(必加,否则Django无法识别表单数量),再添加JS实现新增逻辑:

<form method="POST">
    {% csrf_token %}
    <!-- 渲染问题表单 -->
    <div>
        {{ qform.as_p }}
    </div>

    <!-- 表单集管理字段,必须保留 -->
    {{ choice_formset.management_form }}

    <!-- 所有选项输入框的容器 -->
    <div id="choices-container">
        {% for form in choice_formset %}
            <div class="choice-item">
                {{ form.as_p }}
            </div>
        {% endfor %}
    </div>

    <!-- 新增按钮 -->
    <button type="button" id="add-choice-btn">+ 新增另一个选项</button>
    <button type="submit">创建投票</button>
</form>

<script>
// 动态新增选项逻辑
document.getElementById('add-choice-btn').addEventListener('click', function() {
    const container = document.getElementById('choices-container');
    const items = container.querySelectorAll('.choice-item');
    const lastItem = items[items.length - 1];
    const newItem = lastItem.cloneNode(true);
    
    // 更新新表单的序号
    const regex = new RegExp(`form-(\\d+)-`, 'g');
    const newIndex = items.length;
    newItem.innerHTML = newItem.innerHTML.replace(regex, `form-${newIndex}-`);
    
    // 清空新输入框的内容
    newItem.querySelector('input').value = '';
    
    container.appendChild(newItem);
    // 更新表单集的总数量
    document.getElementById('id_form-TOTAL_FORMS').value = newIndex + 1;
});
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 17:15:04