首页 > 解决方案 > Django Admin Inline 重复查询

问题描述

在我的管理页面中,我有 Order 模型和 OrderItem 模型的 TabularInline

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.Order 2.Product 3.Variant

一对多:product_add_ons

与 select_related/prefetch 相关,只减少了 19 个查询,但是发现了 35 个重复/相似查询

截屏

请注意以下事实:

  1. 所有重复的查询共享

没有按住选择的滚动光标

  1. 删除内联会删除所有重复的查询。

  2. 删除任何 FK 或 ManyToMany 也大大减少了重复查询

  3. 删除 select_related/prefetch_related 将导致

70 个查询,包括 55 个相似查询和 35 个重复查询

任何想法为什么会发生这种情况?

标签: djangodjango-modelsdjango-viewsdjango-formsdjango-templates

解决方案


经过多次搜索和几次失败尝试后确定。

我终于设法通过使用模型表单并将其添加到管理内联来删除所有重复/相似的查询

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')

推荐阅读