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 и правильно ли они отображаются.
- В шаблоне, где пользователь впервые вводит данные лотереи, ошибка не появляется.
- Возможно, проблема заключается в наличии двух форм в одном представлении; я попробовал поместить кнопку с другим именем для управления в представлении.