Django скрытое поле обязательное поле ошибка в двойной форме в представлении [дубликат]

Я разрабатываю Django-страницу, на которой пользователь заполняет форму лотереи. Эти данные хранятся в базе данных MySQL. Часть функциональности страницы заключается в том, что пользователь может извлечь форму с уже введенными данными лотереи, чтобы добавить еще, изменить некоторые или повторно провести лотерею без необходимости повторного ввода всех данных.

Теперь для этой цели у меня есть формы, которые я использую для получения лотереи, добавления участников, добавления данных лотереи и т.д...

class SorteoForm(forms.ModelForm):
    class Meta:
        model = Sorteo
        fields = ['organizer', 'celebration_date', 'budget']
        
class ExclusionForm(forms.Form):
    participants_to_exclude = forms.CharField(label='Participants to exclude', max_length=100)
    
class SorteoRecuperadorForm(forms.Form):
    recuperator_lottery = forms.CharField(label='Lottery code', max_length=50, required=False)
    
class ParticipanteExclusionForm(forms.Form):
    name = forms.CharField(label='', max_length=100, widget=forms.TextInput(attrs={'placeholder': 'Name'}))
    email = forms.EmailField(label='', max_length=100, widget=forms.EmailInput(attrs={'placeholder': 'Email'}))
    exclusions = forms.CharField(label='', max_length=100, required=False, widget=forms.TextInput(attrs={'placeholder': 'Exclusions'}))

ParticipanteExclusionFormSet = formset_factory(ParticipanteExclusionForm)
ParticipanteFormSet = formset_factory(ParticipanteForm)
ExclusionFormSet = formset_factory(ExclusionForm)

Управление данными для этих форм, как для повторного проведения лотереи, так и для получения данных, осуществляется с помощью этого метода:


def recover_lottery(request):
    lottery_form = SorteoForm(request.POST or None)
    ParticipanteExclusionFormSet = formset_factory(ParticipanteExclusionForm, extra=0)
    participant_formset = ParticipanteExclusionFormSet(request.POST or None, prefix='participant')
    recuperator_form = SorteoRecuperadorForm(request.POST or None)
    
    lottery = None
    participants = None
    
    if request.method == 'POST':
        if recuperator_form.is_valid():
            # Retrieve the lottery and participants
            lottery = Sorteo.objects.filter(recover_lottery=recuperator_form.cleaned_data['recuperator_lottery']).first()
            if lottery:
                participants = lottery.participants.all()

        elif lottery_form.is_valid() and participant_formset.is_valid():
            # Logic to save the new lottery

    context = {
        'lottery_form': lottery_form,
        'participant_formset': participant_formset,
        'recuperator_form': recuperator_form,
        'lottery': lottery,
        'participants': participants,
    }
    
    return render(request, 'index/recover_lottery.html', context)

Все это управляется в следующем шаблоне:


<form action="" method="post" onsubmit="return validateForm()">
    {% csrf_token %}
    {{ recuperator_form }}
    <button type="submit" name="recover_lottery">Recover</button>
</form>

{% if lottery %}
<h2>Recovered Lottery</h2>
<form action="" method="post" class="completeForm">
    {% csrf_token %}
    <div class="lotteryForm">
        <div>
            <label for="organizer">Organizer Name</label>
            {{ lottery_form.organizer }}
        </div>
        <div>
            <label for="celebration_date">Celebration Date</label>
            {{ lottery_form.celebration_date }}
        </div>
        <div>
            <label for="budget">Budget</label>
            {{ lottery_form.budget }}
        </div>
    </div>
    {{ participant_formset.management_form }}
    {{ exclusion_formset.management_form }}
    <div id='participant-form-list'>
        {% for form in participant_formset %}
        <div class='participant-form'>
            {{ participant_formset.as_p }}
        </div>
        {% endfor %}
    </div>

    <div id='empty-form-participant' class='hidden'>{{ participant_formset.empty_form.as_p }}</div>
    <div>
        <button class="formButtons addButton" id='add-more' type='button'>Add Participant</button>
        <input class="formButtons doneButton" name="" type="submit" value="Run Lottery">
    </div>
</form>
{% endif %}

С соответствующим JavaScript:


<script>
    function validateForm() {
        var field = document.getElementById('id_recuperator_lottery').value;
        if (field.trim() == '') {
            alert('Please complete the field');
            return false;
        }
        return true;
    }

    /* Logic to load the data into the form */
    function start() {
        document.getElementById("id_organizer").value = "{{ lottery.organizer }}"
        document.getElementById("id_celebration_date").value = "{{ lottery.celebration_date }}"
        document.getElementById("id_budget").value = "{{ lottery.budget }}"
    };

    start()

    /* Complete logic for the run lottery form */
    const addMoreBtn = document.getElementById('add-more');
    const totalNewFormsParticipant = document.getElementById('id_participant-TOTAL_FORMS');

    addMoreBtn.addEventListener('click', add_new_form);

    for (let index = 0; index < 3; index++) { addMoreBtn.click() } function add_new_form(event) {
        if (event) {
            event.preventDefault();
        } const currentParticipants = document.getElementsByClassName('participant-form'); let
            currentFormCountParticipants = currentParticipants.length; const
                formCopyTarget = document.getElementById('participant-form-list'); const
                    copyEmptyFormELParticipant = document.getElementById('empty-form-participant').cloneNode(true);
        copyEmptyFormELParticipant.setAttribute('class', 'participant-form');
        copyEmptyFormELParticipant.setAttribute('id', `form-${currentFormCountParticipants}`); const regex = new
            RegExp('__prefix__', 'g');
        copyEmptyFormELParticipant.innerHTML = copyEmptyFormELParticipant.innerHTML.replace(regex,
            currentFormCountParticipants); totalNewFormsParticipant.setAttribute('value', currentFormCountParticipants + 1);
        formCopyTarget.append(copyEmptyFormELParticipant);
    } </script>

При выполнении этого действия внутри формы я получаю ошибки:

(Hidden field TOTAL_FORMS) *This field is required.
(Hidden field INITIAL_FORMS) *This field is required.

Тесты и гипотезы

  • Отключение операторов if в шаблоне устраняет ошибку до тех пор, пока не будет введен код лотереи, который необходимо извлечь.
  • Если оставить только форму данных лотереи и не извлекать участников/исключений, ошибка не появляется.
  • Проверьте, существуют ли поля TOTAL_FORMS и INITIAL_FORMS и правильно ли они отображаются.
  • В шаблоне, где пользователь впервые вводит данные лотереи, ошибка не появляется.
  • Возможно, проблема заключается в наличии двух форм в одном представлении; я попробовал поместить кнопку с другим именем для управления в представлении.
Вернуться на верх