表单数据未绑定在 Django 中动态添加的内联表单集中

Form data is not bound in dynamically added inline formset in Django

我有一个关于在 Django 中验证动态添加的内联表单集的问题。似乎我在实施中遗漏了一些东西。

这是我的案例: 我的项目是一个团队管理平台。一个团队称为 Crew,可以有多个时间表。每个时间表可以有多个班次。请看看我的代码。目前,如果所有字段都有效,我可以创建一个时间表,其中包含几个动态添加的表单集表单,如果所有字段都有效的话。

如果不是,则不显示 Shift 表单的错误,并再次填充初始数据。发送 POST 请求后,班次表格的数据似乎未绑定(因为 form.is_bound() 为 false)。此外,在 POST 请求之后,不会再次填充 Shift 表单的数据。 您认为造成这种行为的原因是什么?我是否必须覆盖 is_valid 函数?我不知道,因为它看起来功能正常 - 数据只是没有正确绑定到新表单。

Views.py

def schedule_add(request, crew_id):
if request.method == "GET":
    form = ScheduleForm()
    ShiftFormSet = formset_factory(ShiftForm)
    return render(request, 'schedule_add2.html', {'form': form, 'formset': ShiftFormSet, 'title':"Zeitplan hinzufügen"})

elif request.method == "POST":
    form = ScheduleForm(request.POST)
    numberOfShifts = int(request.POST['form-TOTAL_FORMS'])
    ShiftFormSet = formset_factory(ShiftForm, extra=numberOfShifts)
    shift_formset = ShiftFormSet(request.POST, prefix='form')
    print(request.POST)
    if form.is_valid() and shift_formset.is_valid():
        schedule = Schedule()
        schedule.name = form.cleaned_data.get('name')
        schedule.crew = Crew.objects.get(pk=crew_id)
        schedule.location = form.cleaned_data.get('location')
        schedule.subperiod = form.cleaned_data.get('sub_period')
        schedule.save()

        for shift_form in shift_formset:
            if shift_form.is_valid():
                shift = Shift()
                shift.min_user_count = shift_form.cleaned_data.get('min_user_count')
                shift.max_user_count = shift_form.cleaned_data.get('max_user_count')
                shift.start_datetime = shift_form.cleaned_data.get('start_time')
                shift.end_datetime = shift_form.cleaned_data.get('end_time')
                shift.schedule = schedule
                shift.save()
        messages.success(request, 'Zeitplan & Schichten angelegt.')

        return redirect('shifter:crew_view', crew_id=crew_id)
    else:
        messages.error(request, 'Fehler')

    return render(request, 'schedule_add2.html', {'form': form, 'formset': ShiftFormSet, 'title':"Zeitplan hinzufügen"})
else:
    return redirect('shifter:index')

forms.py

class ScheduleForm(forms.ModelForm):
name = forms.CharField(max_length=30, required=True, help_text='', label="Name")
sub_period = forms.ModelChoiceField(queryset=SubPeriod.objects.all(), empty_label=None, label="Tag")
location = forms.ModelChoiceField(queryset=Location.objects.all(), empty_label=None, label="Einsatzort")

class Meta:
    model = Schedule
    fields = ('name', 'sub_period', 'location',)

class ShiftForm(forms.ModelForm):
    min_user_count = forms.IntegerField(required=True, help_text='', label="Min Count", initial=2)
    max_user_count = forms.IntegerField(required=True, help_text='', label="Max Count", initial=4)
    start_time = forms.DateTimeField(required=True, help_text='', label="Shift start", initial=datetime.now)
    end_time = forms.DateTimeField(required=True, help_text='', label="Shift end", initial=datetime.now)

    class Meta:
        model = Shift
        fields = ('start_time','end_time','min_user_count','max_user_count',)

模板

<form method="post">
            {% csrf_token %}

            {% if form.non_field_errors %}
                <div class="alert alert-danger" role="alert">
                  {% for error in form.non_field_errors %}
                    {{ error }}
                  {% endfor %}
                </div>
            {% endif %}

            {% for field in form.visible_fields %}
                {{ field.label_tag }}
                {% if form.is_bound %}
                    {% if field.errors %}
                      {% render_field field class="form-control is-invalid" %}
                      {% for error in field.errors %}
                        <div class="invalid-feedback">
                          {{ error }}
                        </div>
                      {% endfor %}
                    {% else %}
                      {% render_field field class="form-control is-valid" %}
                    {% endif %}
                  {% else %}
                    {% render_field field class="form-control" %}
                  {% endif %}

                  {% if field.help_text %}
                    <small class="form-text text-muted">{{ field.help_text }}</small>
                  {% endif %}
            {% endfor %}

            <h2 class="mt-5">Shifts</h2>
            <table class="table">
                {{ formset.management_form }}

                {% for form in formset.forms %}
                    {% if forloop.first %}
                        <thead>
                        <tr>
                            {% for field in form.visible_fields %}
                                <th>{{ field.label|capfirst }}</th>
                            {% endfor %}
                            <th></th>
                        </tr>
                        </thead>
                    {% endif %}
                    <tr class="formset_row">
                        {% for field in form.visible_fields %}
                            <td>
                                {# Include the hidden fields in the form #}
                                {% if forloop.first %}
                                    {% for hidden in form.hidden_fields %}
                                        {{ hidden }}
                                    {% endfor %}
                                {% endif %}
                                {% if form.is_bound %}
                                    {% if form.errors %}
                                        {% render_field field class="form-control is-invalid" %}
                                        {% for error in form.errors %}
                                            <div class="invalid-feedback">
                                              {{ error }}
                                            </div>
                                        {% endfor %}
                                    {% else %}
                                        {% render_field field class="form-control is-valid" %}
                                    {% endif %}
                                {% else %}
                                    {% render_field field class="form-control" %}
                                {% endif %}
                            </td>
                        {% endfor %}
                        <td></td>
                    </tr>
                {% endfor %}
            </table>
            <button type="submit" class="btn btn-primary">Save</button>
        </form>

提前致谢, 克里斯托弗

您将 class、ShiftFormSet 返回到模板(在代码的 third-from-last 行)而不是实例 shift_formset