优化 Django 中查询集结果的过滤



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

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

想知道这是否可以简化?

(例如数据:假设产品类别是"烘烤"油炸"生"等,项目是"面包"鱼苗"蛋糕"。因此,当 Django 管理中显示项目列表时,所有产品类别都将显示在 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,)

可能您正在寻找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模型之间存在某种关系。希望这有帮助。

呵呵,措辞这个问题在你自己的脑海中很清楚!发布此内容后几分钟就找到了答案:

(我们可以执行objects.all()(单个 SQL 查询(并填充临时字典,而不是在for循环中执行objects.get()。然后使用此临时字典查找关联的字符串值。

def lookups(self, request, model_admin):
qs = model_admin.get_queryset(request)
category_list = {}
for x in ProductCategory.objects.all():
category_list[x.id] = str(x)
ordered_filter_obj_list = []
for i in (
qs.values_list("product_category", flat=True)
.distinct().order_by("product_category")
):
ordered_filter_obj_list.append((i, category_list[i]))
return ordered_filter_obj_list

元组列表中的第一个参数是查找的值,第二个参数只是显示的名称。这可以通过单个SQL查询完成,也可以通过Django ORM完成:

def lookups(self, request, model_admin):
qs = model_admin.get_queryset(request).select_related('product_category')
values = qs.values('product_category_id', 'product_category__name') #assuming ProductCategory has an attribute 'name'
unique_categories = values.distinct('product_category_id', 'product_category__name')
categories = []
for c in unique_categories:
categories.append((c['product_category_id'], c['product_category__name']))
return categories

最新更新