Как динамически удалять формы из несвязанного набора форм без JavaScript в Django

У меня есть решение, но в нем есть одна проблема. Я знаю, где проблема в коде, но не могу ее решить.
Может быть, у кого-то есть решение получше, не содержащее никаких проблем.

Описание проблемы:
После удаления любой формы, поля в остальных формах не предзаполняются если данные недействительны.

Порядок действий:

  1. В браузере отображается 5 форм.
  2. Первое поле первой формы содержит недопустимые данные.
  3. Я активирую флажок удаления в последней форме и нажимаю кнопку «удалить».
  4. Последняя форма удаляется, а первое поле первой формы не предзаполняется.

Причина:
Недействительные данные не попадают в cleaned_data после метода is_valid (), который вызывается в методе not_deleted_forms () класса TestFormSet.

Код:
app_formset.forms.forms

from django import forms

class TestForm(forms.Form):
    title = forms.CharField(label='Title', min_length=5)
    description = forms.CharField(label='Description', max_length=10)

app_formset.forms.formsets

from django.forms.formsets import BaseFormSet

class TestFormSet(BaseFormSet):

    @property
    def not_deleted_forms(self):
        """Return a list of forms that have not been marked for deletion."""
        self.is_valid()

        if not hasattr(self, '_not_deleted_form_indexes'):
            self._not_deleted_form_indexes = []
            for i, form in enumerate(self.forms):
                if i >= self.initial_form_count() and not form.has_changed():
                    self._not_deleted_form_indexes.append(i)
                elif self._should_delete_form(form):
                    continue
                else:
                    self._not_deleted_form_indexes.append(i)

        return [self.forms[i] for i in self._not_deleted_form_indexes]

app_formset.views

from django.views.generic.base import TemplateView

from django.forms.formsets import formset_factory

from .forms.forms import TestForm
from .forms.formsets import TestFormSet

class FormSetView(TemplateView):
    template_name = 'app_formset/formset.html'

    FORMSET = formset_factory(form=TestForm,
                              formset=TestFormSet,
                              extra=0,
                              min_num=1,
                              validate_min=True,
                              can_delete=True,
                              can_delete_extra=True)

    def get_context_data(self, request=None, initial=None, **kwargs):

        context = super().get_context_data(**kwargs)
        context['formset'] = self.FORMSET(request, initial=initial)

        return context

    def post(self, request):

        if 'field_add' in request.POST:
            request_post = request.POST.copy()
            request_post['form-TOTAL_FORMS'] = int(request_post['form-TOTAL_FORMS']) + 1
            context = self.get_context_data(request=request_post)

        elif 'delete' in request.POST:
            formset = self.FORMSET(request.POST)
            initial = [form.cleaned_data for form in formset.not_deleted_forms]
            context = self.get_context_data(initial=initial)

        return render(request, self.template_name, context)
Вернуться на верх