Prevent Django from querying for ForeignKey options for every form in ModelFormSet

微笑、不失礼 提交于 2019-11-28 20:54:06
Michael C. O'Connor

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)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!