#django #django-models #django-views #django-forms #django-templates
#джанго #django-модели #django-просмотры #django-формы #django-шаблоны
Вопрос:
На моей странице администратора у меня есть модель заказа с TabularInline модели OrderItem
class OrderItemStackAdmin(admin.TabularInline):
model = OrderItem
extra = 0
fieldsets = (
(_('Product'), {
'fields': ('product', 'variant')
}), (_('Add-Ons'), {
'fields': ('product_add_ons', 'add_ons_note')
}), (_('Price'), {
'fields': ('quantity', 'product_price', 'add_ons_total_price')
}), (_('Discount'), {
'fields': ('discount',)
})
)
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.select_related(
"customer_order",
"product",
"variant"
).prefetch_related('product_add_ons')
Три внешних ключа: 1.Заказ 2.Продукт 3.Вариант
Один ManyToMany: product_add_ons
С помощью select_related / prefetch related сокращено только 19 запросов, однако найдено 35 повторяющихся / похожих запросов.
Пожалуйста, обратите внимание на приведенные ниже факты:
- ВСЕ дублированные запросы совместно используются
НЕТ КУРСОРА ПРОКРУТКИ С УДЕРЖАНИЕМ ДЛЯ ВЫБОРА
- Удаление встроенного удаляет все дублированные запросы.
- Удаление любых FK или ManyToMany также значительно сокращает количество дублированных запросов
- Удаление select_related/prefetch_related приведет к
70 запросов, включая 55 похожих и 35 дубликатов
Есть идеи, почему это происходит?
Ответ №1:
Хорошо после многих поисков и нескольких неудачных попыток.
Мне, наконец, удалось удалить все дублированные / похожие запросы, используя Model form и добавив его в admin inline
class OrderItemForm(forms.ModelForm):
""" OrderItem Model Form """
products_choices = [('', '---------')]
for item in Product.objects.values('pk', 'name', 'arabic_name'):
products_choices.append(
(item['pk'], f"{item['arabic_name']}-{item['name']}"))
product = forms.ChoiceField(required=True,
choices=products_choices)
variants_choices = [('', '---------')]
variants_choices.extend(Variants.objects.values_list('pk', 'name'))
variant = forms.ChoiceField(required=False,
choices=variants_choices)
class OrderItemStackAdmin(admin.TabularInline):
""" Stacked Order Items """
model = OrderItem
form = OrderItemForm
autocomplete_fields = ['product_add_ons']
extra = 0
fieldsets = (
(_('Product'), {
'fields': ('product', 'variant')
}), (_('Add-Ons'), {
'fields': ('product_add_ons', 'add_ons_note')
}), (_('Price'), {
'fields': ('quantity', 'product_price', 'add_ons_total_price')
}), (_('Discount'), {
'fields': ('discount',)
})
)
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.prefetch_related('product_add_ons')
Комментарии:
1. Я думаю
extra = 0
, этого достаточно, не так ли?2. После многих поисков и неудачных попыток это кажется единственным решением. Спасибо.
3. @marke К сожалению, extra=0 не решит проблему, если там больше, чем заполненных строк.
4. разве это не приводит к ошибке? что происходит, когда кто-то добавляет экземпляр варианта, а сервер тем временем не сбрасывается? OrderItemForm не будет оцениваться снова, и новой опции не будет, нет?
5. Вы правы. Вариант не будет существовать, если он был создан в том же экземпляре сервера.