2015-09-23 108 views
0

的第一件事Django的內聯表單集並在您提交的數據是它的每一個循環的形式觸發驗證:爲formset Django中的ModelChoiceField優化驗證?

for i in range(0, self.total_form_count()): 
    form = self.forms[i] 
    self._errors.append(form.errors) 

在圖片中,其中該formset是行對個人形式,驗證工作表行由行。如果表單中有ModelChoiceField,則將在ModelChoiceField的查詢集中查找每行中選定的值,從而每行至少再添加一個數據庫命中。

key = self.to_field_name or 'pk' 
value = self.queryset.get(**{key: value}) 

現在,如果所有這些查詢集都是相同的(如我的),這似乎是一種浪費。查詢集不會逐行更改,有什麼方法可以緩存它嗎?

更一般地說,在列中進行驗證會更有效率,例如,首先收集窗體類的字段,並對每個字段(列)的所有表單(行)進行循環?

回答

0

您可以避免通過與早期的代碼填入選擇feeded正常ChoiceField更換ModelChoiceField,例如查詢集:

class YourModelForm(forms.ModelForm) 
    your_foreign_field = forms.ChoiceField(choices=list(YourForeignModel.objects.values_list('id', 'display_name'))) 

這樣,查詢集將被執行一次,當類(而非類對象)創建。但是這會導致一些麻煩 - 在應用程序啓動時(或第一次達到此代碼時)將填充外來對象列表。爲了避免這種情況,您可以將您的選擇,__init__

class YourModelForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     choices = kwargs.pop('your_foreign_choices') 
     super(YourModelForm, self).__init__(*args, **kwargs) 
     self.fields['your_foreign_field'] = forms.ChoiceField(choices=choices) 

這樣,所有你需要做的是通過填充的選擇,你的表單集(這樣會進一步通過,爲每個窗體):

YourModelFormSet = modelformset_factory(YourModelForm) 

def your_view(request): 
    formset = YourModelFormSet(form_kwargs={'your_foreign_choices': list(YourForeignModel.objects.values_list('id', 'display_name'))}) 
+0

但是,然後你失去了所有的模型的好處,就像開箱即用的驗證,保存等... –

+0

保存做得不錯,也驗證 - 除非你的選擇產生錯誤,但你也可以在這裏使用'ModelChoiceField' ,它應該可以正常工作。對選擇使用'ModelChoiceField'將會阻止執行查詢集,字段將使用預先填充的選項。 – GwynBleidD