我正在覆盖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