Django: очистка и проверка ФОРМ, которые зависят друг от друга

Документы django охватывают очистку и проверку ПОЛЕЙ, которые зависят друг от друга, но я не могу найти ничего, что покрывает формы, которые зависят друг от друга.

У меня есть одна форма HTML, которая содержит как стандартную форму django, так и набор форм django. Надлежащая проверка каждой формы в наборе форм полностью зависит от значения из основной формы (например, установите флажок в основной форме и определенное поле в каждой форме в наборе форм< /em> внезапно становится обязательным).

Моя интуиция состоит в том, чтобы «просто» передать всю основную форму в вызов проверки набора форм, например так:

def my_view(request):
    MyFormSet = formset_factory(MyForm, extra=2, can_order=True)

    if request.method == 'POST':
        form = MainForm(request.POST)
        formset = MyFormSet(request.POST)

        if form.is_valid() and formset.is_valid(form): # <-- ?!?!
            # The formset is now validated based on the form

Однако, чтобы заставить это работать, я считаю, что мне придется переопределить как набор форм is_valid(), так и базовые методы формы is_valid() и clean(). Таким образом, это становится довольно грязным довольно быстро.

Есть лучший способ это сделать?


person Dolph    schedule 14.08.2011    source источник


Ответы (2)


Однажды я пытался сделать что-то подобное, и это руководство http://yergler.net/blog/2009/09/27/nested-formsets-with-django/ оказался довольно полезным.

Другой способ сделать это:

def my_view(request):
MyFormSet = formset_factory(MyForm, extra=2, can_order=True)

if request.method == 'POST':
    form = MainForm(request.POST)
    formset = MyFormSet(request.POST, other_form = form)

    if form.is_valid() and formset.is_valid(): # <-- ?!?!
        # The formset is now validated based on the form

Затем

class MyFormSet(...):

   def __init__(self, *args, **kwargs):
       if kwargs.has_key('other_form'):
           self.myformforlater = kwargs.pop('other_form')
       Super(MyFormSet, self).__init__(*args, **kwargs)

Таким образом, вам нужно только переопределить метод init, и у вас будет доступ к внешней форме с любого шага проверки.

person Ted    schedule 14.08.2011
comment
Это дало мне 80% пути к решению, поэтому я принимаю его, но также публикую свое полное решение для справки. - person Dolph; 15.08.2011

Вот код, который я получил, используя ответ Теда (django 1.3):

class BaseMyFormSet(BaseFormSet):
    main_form = None

    def __init__(self, *args, **kwargs):
        # Save the main form until validation
        if kwargs.has_key('main_form'):
            self.main_form = kwargs.pop('main_form')

        super(BaseMyFormSet, self).__init__(*args, **kwargs)

    def clean(self):
        if any(self.errors):
            # Don't bother validating the formset unless each 
            # form is valid on its own
            return

        checkbox = self.main_form.cleaned_data['my_checkbox']

        if checkbox:
            for form in self.forms:
                # Do some extra validation


def my_view(request):
    MyFormSet = formset_factory(MyForm, extra=2, can_order=True,
        formset=BaseMyFormSet)

    if request.method == 'POST':
        form = MainForm(request.POST)
        formset = MyFormSet(request.POST, main_form=form)

        if form.is_valid() and formset.is_valid():
            # The formset is now validated based on the form
person Dolph    schedule 14.08.2011