Причина, по которой ModelChoiceField
, в частности, создает попадание при создании вариантов - независимо от того, был ли QuerySet заполнен ранее, - заключается в этой строке
for obj in self.queryset.all():
в django.forms.models.ModelChoiceIterator
.Как подчеркивает документация Django по кэшированию QuerySets ,
вызываемые атрибуты вызывают поиск БД каждый раз.
Поэтому я бы предпочел просто использовать
for obj in self.queryset:
, хотя я не уверен на 100% во всех последствиях этого (я знаю, что у меня нет больших планов с набором запросов впоследствии, поэтому я думаю, что я в порядке без копии .all()
создает).Я испытываю желание изменить это в исходном коде, но так как я собираюсь забыть об этом при следующей установке (и это плохой стиль для начала), я закончил тем, что написал свой пользовательский ModelChoiceField
:
class MyModelChoiceIterator(forms.models.ModelChoiceIterator):
"""note that only line with # *** in it is actually changed"""
def __init__(self, field):
forms.models.ModelChoiceIterator.__init__(self, field)
def __iter__(self):
if self.field.empty_label is not None:
yield (u"", self.field.empty_label)
if self.field.cache_choices:
if self.field.choice_cache is None:
self.field.choice_cache = [
self.choice(obj) for obj in self.queryset.all()
]
for choice in self.field.choice_cache:
yield choice
else:
for obj in self.queryset: # ***
yield self.choice(obj)
class MyModelChoiceField(forms.ModelChoiceField):
"""only purpose of this class is to call another ModelChoiceIterator"""
def __init__(*args, **kwargs):
forms.ModelChoiceField.__init__(*args, **kwargs)
def _get_choices(self):
if hasattr(self, '_choices'):
return self._choices
return MyModelChoiceIterator(self)
choices = property(_get_choices, forms.ModelChoiceField._set_choices)
Это не решает общую проблему кэширования базы данных, но, поскольку вы спрашиваете о ModelChoiceField
в частности, и именно это заставило меня задуматься об этом кэшировании, я подумал, что это может помочь.