2011-08-14 67 views
5

Django文檔包括cleaning and validating FIELDS that depend on each other的形式,但我無法找到任何覆蓋了互相依賴的形式。Django的:清潔和驗證依賴於彼此

我有與含有一個標準的django形式和一個Django表單集的單個HTML表單。在該formset的每種形式適當的驗證是完全條件基於從主模中的值(例如檢查主窗體上的一個盒,和一個特定的字段上每種形式在該formset突然變得必需的)。

我的直覺是「簡單的」傳遞整個主要形式到表單集驗證調用,就像這樣:

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()方法。所以,它非常快速地變得非常混亂。

有沒有更好的方式來做到這一點?

回答

6

這是我最後的代碼,使用特德的回答(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 
+0

這應該是被接受的答案。 –

8

我調查一次做這樣的事情,而本教程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方法,你有任何驗證步驟訪問外部形式。

+0

這引起了我的方式來解決80%,所以我接受它,但也張貼我的完整解決方案以供參考。 – Dolph