在formang Django中优化ModelChoiceField的验证?

时间:2015-09-23 08:52:04

标签: django validation formset

Django的内联formset在提交数据时所做的第一件事就是在循环中对每个表单进行触发验证:

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})

现在,如果所有这些查询集都相同(就像我的一样),这似乎是一种浪费。查询集不会在行之间发生变化,有没有办法缓存它?

更一般地说,在列中进行验证是否更有效,例如,首先从表单的类中收集字段,然后遍历每个字段(列)的所有表单(行)?

1 个答案:

答案 0 :(得分:-1)

您可以通过将ModelChoiceField替换为代码中先前填充的选项所支持的普通ChoiceField来避免该查询集,例如:

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

这样,当创建类(不是类对象)时,queryset将被执行一次。但这会导致一些麻烦 - 应用程序启动时(或第一次到达此代码时)将填充外部对象列表。为避免这种情况,您可以将选择移至__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)

这样你需要做的就是将填充的选项传递给你的formset(因此它将被进一步传递到每个表单中):

YourModelFormSet = modelformset_factory(YourModelForm)

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