2013-03-04 41 views
6

我正在为我的Django应用程序构建一个csv导入表单,并希望为了验证目的而在ModelFormSet中显示要导入的行。阻止Django为ModelFormSet中的每个表单查询ForeignKey选项

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

的问题是,该模型在表单集数据库查询,以便填充ModelChoiceField的选项发出各种形式通过ForeignKey领域和每个字段引用其他三款车型。

为什么Django不缓存表单(因为它已被多次使用)或者是否已有方法可以完成这个我不知道的事情呢?

+1

django1.5有模型内存缓存。 – danihp 2013-03-04 14:27:33

+1

你说得对(https://docs.djangoproject.com/en/1.5/releases/1.5/#caching-of-related-model-instances),但不幸的是它不会影响这个问题。 – jnns 2013-03-04 23:22:49

+0

我已经做了一些小技巧来解决这个问题:http://stackoverflow.com/a/43105646/8450 – 2017-03-29 23:07:15

回答

11

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

缓存也可能会导致意外的副作用 - 例如,窗体的__init__功能可能是依赖于它接收到的initial数据,使缓存form对象不正确。

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

你的形式将需要直接接受的选择一个构造函数:

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 

而且你的表单集将需要重写运行的查询集,并将它们传递到形式的方法,因为他们正在构建:

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

(见the Django source寻找到如何做到这一点的工作)

+0

感谢您花时间回答我的问题。您的解决方案就是我的想法,但现在我知道这是一条路! – jnns 2013-03-07 14:23:30

+0

我使用这个解决方案的同样的问题,但当保存我得到“不能分配”u'7'“:”Stop.city“必须是”城市“的实例。” Stop是具有City fk的ModelForm(用于构建formset)。有没有什么办法可以传递它呢?似乎需要花费太多的时间来进一步这样做。 – mariodev 2013-07-20 13:52:50

+0

@mariodev,我想你可能需要发布一些更多的代码来帮助解释/追踪这个问题。这个正义可能没有足够的评论空间,所以它可能更适合自己的问题。 – 2013-07-23 16:39:55

相关问题