为 django 表单集添加按钮

问题描述 投票:0回答:1

我开始使用 Django 5,并且正在构建一个 Web 项目来组织秘密圣诞老人礼物交换。

我的问题是,使用表单集时,它们不是动态的,因此我无法根据用户的请求创建可变数量的表单。

我有这个表格:

class ParticipanteForm(forms.ModelForm):
    class Meta:
        model = Participante
        fields = ['nombre', 'email']

ParticipanteFormSet = formset_factory(ParticipanteForm)

此型号:

class Participante(models.Model):
    sorteo = models.ForeignKey(Sorteo, related_name='participantes', on_delete=models.CASCADE)
    nombre = models.CharField(max_length=100)
    email = models.EmailField()

这个视图是我渲染表单并保存数据的地方:


def crear_sorteo(request):
    sorteo_form = SorteoForm(request.POST or None)
    ParticipanteFormSet = formset_factory(ParticipanteForm, extra=3)
    participante_formset = ParticipanteFormSet(request.POST or None)
    
    context = {
        'sorteo_form': sorteo_form,
        'participante_formset': participante_formset,
    }
    
    if request.method == 'POST':
        if sorteo_form.is_valid():
            sorteo = sorteo_form.save()  # Save the draw first
            if participante_formset.is_valid():
                for participante_form in participante_formset:
                    participante = participante_form.save(commit=False)
                    participante.sorteo = sorteo  # Assign the draw to the participant
                    participante.save()
                return render(request, 'sorteo_realizado.html')
    
    return render(request, 'crear_sorteo.html', context)

如您所见,ParticipanteFormSet = formset_factory(ParticipanteForm, extra=3) 取决于您指定的 extra 数量,这将是要创建的表单数量。但我想在模板中:

<body>
    <form action="" method="post">
        {% csrf_token %}
        {{ sorteo_form }}
        {{ participante_formset.management_data }} 
        {{ participante_formset.as_p }}
        <input type="submit" value="Realizar sorteo">
    </form>
</body>

有一个添加参与者的按钮,以便用户可以输入任意数量的用户,且参与者至少为 3 人。

我尝试制作一个发布按钮,收到后,

extra
的数量更新为+1,但页面重新加载并且数据丢失。如果有人知道如何实现这一点,那将非常有帮助,提前致谢。

javascript html django django-views django-forms
1个回答
0
投票

我终于解决了这个问题:在模板中,我们需要添加以下 Django 变量 {{ attendee_formset.management_form }} ,它允许我们使用表单,此外还添加一个按钮来添加将调用 JavaScript 函数的参与者负责添加具有不同 ID 的表单,以便它们最终不会具有相同的名称。最后,模板看起来像这样:

<body>
    <style>
        .hidden {
            display: none;
        }
    </style>
    <form action="" method="post">
        {% csrf_token %}
        {{ sorteo_form }}
        {{ participante_formset.management_form }}
        <div id='participante-form-list'>
            {% for form in participante_formset %}
            <div class='participante-form'>
                {{ participante_formset.as_p }}
            </div>
            {% endfor %}
        </div>
        <div id='empty-form' class='hidden'>{{ participante_formset.empty_form.as_p }}</div>
        <button id='add-more' type='button'>+ participant</button>
        <input type="submit" value="Carry out draw">
    </form>
</body>

与 JavaScript 一起:

<script>
    const addMoreBtn = document.getElementById('add-more')
    const totalNewForms = document.getElementById('id_participante-TOTAL_FORMS')
    addMoreBtn.addEventListener('click', add_new_form)

    function add_new_form(event) {
        if (event) {
            event.preventDefault()
        }

        const currentParticipantes = document.getElementsByClassName('participante-form')
        let currentFormCount = currentParticipantes.length

        const formCopyTarget = document.getElementById('participante-form-list')
        const copyEmptyFormEL = document.getElementById('empty-form').cloneNode(true)
        copyEmptyFormEL.setAttribute('class', 'participante-form')
        copyEmptyFormEL.setAttribute('id', `form-${currentFormCount}`)
        const regex = new RegExp('__prefix__', 'g')
        copyEmptyFormEL.innerHTML = copyEmptyFormEL.innerHTML.replace(regex,
        currentFormCount)
        totalNewForms.setAttribute('value', currentFormCount + 1)

        formCopyTarget.append(copyEmptyFormEL)
    }
</script>

最后,在视图中,我们只需要声明formset并将extra设置为0即可:

ParticipanteFormSet = formset_factory(ParticipanteForm, extra=0)

感谢以下视频,我得到了此代码,这对您和我来说肯定都会非常有帮助:

https://youtu.be/s3T-w2jhDHE?si=agQ07IQGP__QAitk

© www.soinside.com 2019 - 2024. All rights reserved.