2015-09-23 74 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