Встроенные дублированные запросы Django Admin

#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 повторяющихся / похожих запросов.

Скриншот

Пожалуйста, обратите внимание на приведенные ниже факты:

  1. ВСЕ дублированные запросы совместно используются

НЕТ КУРСОРА ПРОКРУТКИ С УДЕРЖАНИЕМ ДЛЯ ВЫБОРА

  1. Удаление встроенного удаляет все дублированные запросы.
  2. Удаление любых FK или ManyToMany также значительно сокращает количество дублированных запросов
  3. Удаление 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. Вы правы. Вариант не будет существовать, если он был создан в том же экземпляре сервера.