Как лучше всего использовать `ModelChoiceField` в `NestedTabularInline`?
Недавно я заметил, что детальный экран в моей паутине работает очень медленно. Проанализировав проблему, я обнаружил, что она вызвана полем inline
, содержащим ModelChoiceField
при слишком большом количестве экземпляров. Это поле многократно выполняет SELECT *
запросы к базе данных, значительно замедляя время загрузки экрана.
Например: у этой линии было 50 экземпляров, теперь у нее 50 ModelChoiceField
, что увеличивает 50 SELECT *
Я пробовал различные решения, включая установку queryset на objects.none()
Однако такой подход привел к новой проблеме: при редактировании данные не автовыбираются, как ожидалось. Я попытался решить эту проблему, установив начальное значение динамически в методе __init__
, но это не сработало из-за отсутствия набора queryset.
class ProductOptionForm(CustomDuplicateItemInlineForm):
class Meta:
model = ProductOption
fields = '__all__'
# override option để hiển thị autocomplete với size option
option = forms.ModelChoiceField(
queryset=PodOption.objects.none(),
required=True,
widget=CustomOptionSelect2(
url='product-size-options-auto-complete',
),
label='Size Option'
)
def __init__(self, *args, **kwargs):
super(ProductOptionForm, self).__init__(*args, **kwargs)
# Use the preloaded data to set the initial dynamically
if self.instance and self.instance.pk and hasattr(self, 'product_size_options'):
self.fields['option'].initial = self.product_size_options[self.instance.option_id] # Manually set the result cache
Все пусто, как видите
Если кто-нибудь знает решение, пожалуйста, дайте мне знать. Заранее спасибо!
После отладки выяснилось, что проблемы вызывает filter_choices_to_render
из autocomplete.Select2
, поэтому я переопределяю его с предварительно загруженным значением. Этот метод выглядит не очень хорошо, но пока что он работает
class CustomOptionSelect2(autocomplete.Select2):
def filter_choices_to_render(self, selected_choices):
"""Override filter_choices_to_render to prevent access database on initial."""
if hasattr(self, 'initial'):
value = ModelChoiceIteratorValue(
self.initial.pk, self.initial
)
self.choices = [
(value, f"{self.initial.type}: {self.initial.value}")
]
else:
super().filter_choices_to_render(selected_choices)