Django: Почистване и валидиране на ФОРМИ, които зависят един от друг

Документите на django обхващат почистване и валидиране на ПОЛЕТА, които зависят едно от друго, но не мога да намеря нищо, което да обхваща форми, които зависят една от друга.

Имам един HTML формуляр, който съдържа както стандартен django формуляр, така и django formset. Правилното валидиране на всеки формуляр в набора от формуляри е изцяло условно въз основа на стойност от главния формуляр (напр. поставете отметка в квадратче в основния формуляр и конкретно поле във всеки формуляр в набора от формуляри< /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