Почему моя кнопка отправки перемещается за пределы формы Django, когда форма перезагружается из недопустимого сообщения?

У меня есть шаблон, который включает в себя ModelForm, ModelFormSet и кнопку отправки, которая должна отправлять все данные формы как из Form, так и из FormSet. Проблема в том, что когда я отправляю данные, если данные недействительны, иногда шаблон перезагружается с кнопкой отправки, перемещенной за пределы контейнера формы - как это вообще происходит? - и хотя пользователь может редактировать данные в формах, чтобы они были действительными, он больше не может отправлять формы. Кроме того, кнопка отправки не плавает. Я использую кнопку с идентификатором «add_def_report» для динамического добавления форм в набор инцидентов (я добавляю «пустую_форму» в набор инцидентов и меняю идентификаторы). Спасибо за любую помощь!

Шаблон:

<form method="post" class="form-horizontal">

{% crispy incident_form %}

<input type="button" id="delete_field_data" class="btn btn-outline-danger" value="Delete Field Incident Data">

<div id="form_set_class">
  {{ incident_formset.management_form }}
  {% for form in incident_formset %}
    {{form.non_field_errors}}
    {{form.errors}}
    {% crispy form %}
  {% endfor %}
</div>

<p>Add a part deficiency report for each component which needs repair or replacement</p>
<input type="button" id="add_def_report" class="btn btn-outline-dark" value="Add Part Deficiency Report">

<div id="empty_form" style="display:none">
  <div id="incident___prefix__">

    <fieldset>
      <legend>Part Deficiency Report</legend>
      {{incident_formset.empty_form}}
      <br>
      <input type="button" id='delete_incident___prefix__' class="btn btn-outline-danger" value="Delete Part Deficiency Report" onclick="delete_def_report()">
    </fieldset>

  </div>
</div>

<input type="submit" class="btn btn-outline-primary custom-submit" value="Submit">
</form>

CSS:

.center-text{
  display: block;
  text-align: center;
}

form{
  display: inline-block;
  margin-right: auto;
  margin-left: auto;
  text-align: left;
}

legend {
  float: left; /*allows for top margin */
  border-bottom: 1px solid black;
  margin-bottom: 20px;
  margin-top: 20px;
}

#form_set_class{
  width: auto;
  text-align: left;
}

#form_set_class *{
  display: block;
}

#add_def_report{
  text-align: left;
}

просмотров.py:

def new_incident(request):

if request.method == 'POST':
    incident_form = IncidentForm(request.POST)
    deficiency_formset = DeficiencyFormSet(request.POST)

    if deficiency_formset.is_valid() and incident_form.is_valid():
        incident_form.save()
        forms = deficiency_formset.save()
        for form in forms:
            form.save()
        return redirect('quality_dept:home')

    else:
        dict = {'incident_form': incident_form, 'incident_formset': deficiency_formset}
        return render(request, 'incidents/new_incident.html', dict)

else:
    incident_form = IncidentForm()
    formset_data = { 'form-TOTAL_FORMS': '0',
                     'form-INITIAL_FORMS': '0',
                     'form-MAX_NUM_FORMS': '20'}
    def_formset = DeficiencyFormSet(formset_data)
    dict = {'incident_form': incident_form, 'incident_formset': def_formset}
    return render(request, 'incidents/new_incident.html', dict)

формы.py:

class IncidentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(IncidentForm, self).__init__(*args, **kwargs)

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset("General Information", 'incident_id', 'qc_rep', 'date_filed'),
            Fieldset("Contract Data", "job", "contract", "unit"),
            Fieldset("Description", "description", "resolved", "resolution"),
            Fieldset("Field Incident Data", "field_incident", "gov_poc",
        "location_of_unit", "shipping_address", id="field_incident_fieldset")
    )
        self.helper.form_id = "incident_form"

    class Meta:
        model = Incident
        fields = "__all__"

class PartDeficiencyForm(forms.ModelForm):
    class Meta:
        model = PartDeficiency
        fields = "__all__"

DeficiencyFormSet = modelformset_factory(model=PartDeficiency, form=PartDeficiencyForm, exclude=None, extra=0, max_num=20, can_delete=True)

person soporific312    schedule 18.06.2019    source источник
comment
Пожалуйста, покажите IncidentForm и IncidentForm. Передача formset_data для запросов GET необычна. Обычно вы делаете def_formset = DeficiencyFormSet() для запросов GET и устанавливаете начальное и максимальное количество форм при вызове formset_factory.   -  person Alasdair    schedule 18.06.2019
comment
@Alasdair Я добавил свой модуль forms.py. Не могли бы вы пояснить свой комментарий дальше? Я моделировал свой набор форм на основе документа Django, который дает следующий пример: docs.djangoproject.com/en/2.2/topics/forms/formsets/. Позже: вы могли заметить дополнительные данные (form-TOTAL_FORMS, form-INITIAL_FORMS и form-MAX_NUM_FORMS), которые требовались в данных набора форм выше. Эти данные необходимы для ManagementForm. Эта форма используется набором форм для управления коллекцией форм, содержащихся в наборе форм. Если вы не предоставите эти данные управления, будет возбуждено исключение.   -  person soporific312    schedule 18.06.2019
comment
Форма управления требуется только для запросов POST. Если вы делаете def_formset = DeficiencyFormSet() для запроса GET, то форма не привязана, поэтому Django не пытается проверить форму. Это был просто комментарий - он не объясняет, почему ваш тег формы находится не в том месте. Я не могу сразу определить проблему, поэтому я бы поэкспериментировал с удалением функциональности формы js/crispy, чтобы попытаться сузить круг причин проблемы.   -  person Alasdair    schedule 18.06.2019
comment
@Alasdair Хорошо, но если я сделаю дефицит_формсет = ДефицитФормсет(запрос.POST) после POST, набор форм должен быть привязан в этот момент правильно? И тогда метод is_valid() должен возвращать список форм? Потому что, когда я отправляю правильно заполненную форму, я не получаю формы из набора форм - он пуст. Обе эти проблемы — кнопка отправки, перемещающаяся по недопустимым формам, и отсутствие форм в действительном наборе форм — меня очень смущают. Особенно кнопка отправки — как элемент просто выходит из формы/div?   -  person soporific312    schedule 20.06.2019
comment
Метод is_valid() возвращает True или False в зависимости от того, допустимы ли отправленные данные. Я не могу объяснить проблему, которую вы видите в шаблоне.   -  person Alasdair    schedule 20.06.2019


Ответы (1)


Итак, я нашел исправление для запутанного поведения кнопки отправки — я заключил все в тегах формы в div. Очевидно, это работает, но технически не отвечает на мой вопрос, поскольку не объясняет, почему это произошло. Но я опубликую это как ответ, чтобы отделить его от комментариев по устранению неполадок выше. Если я найду ответ на вопрос, почему, я добавлю его сюда.

person soporific312    schedule 19.06.2019