首页 > 解决方案 > 优化Django中Queryset结果的过滤

问题描述

我正在覆盖Django Admin's list_filter(自定义显示在 django 管理 UI 右侧的列表视图的过滤器)。以下代码有效,但未优化:它通过“产品类别数”增加 SQL 查询。

(以下代码示例中要关注的部分是,qs.values_list('product_category', flat=True)它只返回一个id(int),所以我必须使用ProductCategory.objects.get(id=i).)

想知道这是否可以简化?

(例如数据:假设产品类别为“baked”“fried”“raw”等,Items为“bread”“fish鱼”“cake”。所以当在Django Admin中显示Item列表时,所有产品类别将显示在 UI 右侧的“过滤依据”列中。)

from django.utils.translation import ugettext_lazy as _
from django.contrib.admin import SimpleListFilter
from product_category.model import ProductCategory


class ProductCategoryFilter(SimpleListFilter):
    title = _('ProductCategory')
    parameter_name = 'product_category'

    def lookups(self, request, model_admin):
        qs = model_admin.get_queryset(request)

        ordered_filter_obj_list = []
        # TODO: Works, but increases SQL queries by "number of product categories"
        for i in (
            qs.values_list("product_category", flat=True)
            .distinct()
            .order_by("product_category")
        ):
            cat = ProductCategory.objects.get(id=i)
            ordered_filter_obj_list.append((i, cat))

        return ordered_filter_obj_list

    def queryset(self, request, queryset):
        if self.value():
            return queryset.filter(product_category__exact=self.value())



# P.S. Above filter is used in another class like so
class ItemAdmin(admin.ModelAdmin):
    list_filter = (ProductCategoryFilter,)

标签: djangodjango-models

解决方案


可能您正在寻找select_related,我不知道您的确切模型结构,但您可以按如下方式使用它:

cats = set()

for p in Product.objects.all().select_related('category'):
    # Without select_related(), this would make a database query for each
    # loop iteration in order to fetch the related categories  for each product.
    cats.add(p.category)

我假设您的产品和ProductCategory模型之间存在某种关系。希望这有帮助。


推荐阅读