防止Django从ModelFormSet中的每个表单查询ForeignKey选项 [英] Prevent Django from querying for ForeignKey options for every form in ModelFormSet

查看:120
本文介绍了防止Django从ModelFormSet中的每个表单查询ForeignKey选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的Django应用程序构建一个csv导入表单,并希望以 ModelFormSet 的形式显示要导入的行。

因此,我添加了一个视图到相关的 ModelAdmin ,它从csv读取行并打印一个 ModelFormSet (queryset = an_empty_queryset,initial = {data_from_the_csv})



问题是模型通过 ForeignKey 字段和表单中的每个表单中的每个字段都会发出数据库查询,以填充 ModelChoiceField 的选项。



为什么Django不缓存表单(因为它被使用了好几次)还是有一种方法来完成这个我不知道还有吗

解决方案

Django Formsets只是将表单创建的所有细节委托给表单对象本身,并且单个表单实例不知道的其他人,所以并不意外,每个人都必须查询自己的选择。



缓存也可能会产生意想不到的副作用 - 例如,窗体的 __ init __ 函数可能依赖于 initial 收到的数据,使缓存的表单对象不正确。



减少查询数量的最佳方式是检索一次选择查询集,然后将其传递给构造函数中的表单类。这将需要定义一个自定义的 ModelForm 和一个自定义的 ModelFormSet



您的表单将需要直接接受选项的构造函数:

 从django.forms.models import ModelForm 

class MyForm(ModelForm):
def __init __(self,my_field_choices = None,* args,** kwargs):
super(MyForm,self).__ init __(* args,** kwargs)
self.fields ['my_field']。choices = my_field_choices

您的表单将需要重写一个方法来运行查询器,并将它们传递到表单中:

  from django.forms .models import BaseModelFormSet 

class MyFormSet(BaseModelFormSet):
def _construct_forms(self):
#实例化所有的表单,并将它们放在self.forms
self中。 forms = []

#定义每个选项querysets
my_field_choices = Model.ob ject.filter(...)

#将您的查询结果添加到dict中以传递到表单
form_defaults = {'my_field_choices':my_field_choices,}

对于我在xrange(min(self.total_form_count(),self.absolute_max)):
self.forms.append(self._construct_form(i,** form_defaults))

(请参阅 Django来源,以了解如何运作)


I'm building a csv import form for my Django application and want to display the to-be-imported rows in a ModelFormSet for validational purposes.

Therefore I added a view to the relevant ModelAdmin which reads the lines from the csv and prints a ModelFormSet(queryset=an_empty_queryset, initial={data_from_the_csv}).

The problem is that the model references three other models via ForeignKey fields and for each field in each form in the formset a database query is issued in order to populate the ModelChoiceField's options.

Why doesn't Django cache the form (as it is used several times) or is there already a way to accomplish this I don't know about yet?

解决方案

Django formsets just delegate all the details of form creation to the form objects themselves, and the individual form instances aren't aware of the others, so it isn't unexpected that each will have to query for its own choices.

Caching could also have unintended side effects--for example, the form's __init__ function could be dependent on the initial data it received, making the cached form object incorrect.

The best way to reduce the number of queries would be to retrieve the choice querysets once and then pass them to your form classes in their constructor. This will require defining a custom ModelForm and a custom ModelFormSet.

Your form will need a constructor that accepts the choices directly:

from django.forms.models import ModelForm

class MyForm(ModelForm):
    def __init__(self, my_field_choices=None, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['my_field'].choices = my_field_choices

And your formset will need to override a method to run the querysets and pass them into the forms as they're constructed:

from django.forms.models import BaseModelFormSet

class MyFormSet(BaseModelFormSet):
    def _construct_forms(self):
        # instantiate all the forms and put them in self.forms
        self.forms = []

        # Define each of your choices querysets
        my_field_choices = Model.object.filter(...)

        #Add your querysets to a dict to pass to the form
        form_defaults = {'my_field_choices': my_field_choices, }

        for i in xrange(min(self.total_form_count(), self.absolute_max)):
            self.forms.append(self._construct_form(i, **form_defaults))

(see the Django source to look into how this would work)

这篇关于防止Django从ModelFormSet中的每个表单查询ForeignKey选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆