防止Django从ModelFormSet中的每个表单查询ForeignKey选项 [英] Prevent Django from querying for ForeignKey options for every form in ModelFormSet
问题描述
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屋!