我正在开发一个围绕PostgreSQL数据仓库应用程序的Django管理包装器,该应用程序包含一些包含数百万条记录的表。
管理员更改列表页面,没有任何列表过滤器,加载到一秒钟,但如果我在管理员list_filters
中包含某些列,则加载速度非常慢,并且可能需要30秒到1分钟加载
检查数据库,我看到了几个查询:
SELECT DISTINCT "warehouse_data"."filter_field1" FROM "warehouse_data" ORDER BY "warehouse_data"."filter_field1" ASC;
每一个只需要3-5秒,但就像其中有十几个,这些加起来。所有字段都已编入索引,因此我不确定如何加速它们。如何提高管理员绩效?我如何插入Django的缓存机制来缓存这些列表过滤器的实际查询?
答案 0 :(得分:0)
如您所见;缓慢的原因是django会编译唯一值列表,以便它可以在边栏中显示它们。
在后台,这需要对数据库进行全表扫描,这在您的表很大时非常昂贵。如果您将此字段用作list_filter;唯一值的数量很可能很小,并且您可以自己更有效地生成唯一值列表(假设您知道这些值来自何处)。为此,您可以定义一个自定义的list_filter。
来自the docs(出于卑鄙而浓缩):
list_filter应该是元素的列表或元组,其中每个元素 应该是以下类型之一:
- 字段名
- 从django.contrib.admin.SimpleListFilter继承的类
from datetime import date
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
class DecadeBornListFilter(admin.SimpleListFilter):
title = _('decade born')
parameter_name = 'decade'
def lookups(self, request, model_admin):
return (
('80s', _('in the eighties')),
('90s', _('in the nineties')),
)
def queryset(self, request, queryset):
# Compare the requested value (either '80s' or '90s')
# to decide how to filter the queryset.
if self.value() == '80s':
return queryset.filter(birthday__gte=date(1980, 1, 1),
birthday__lte=date(1989, 12, 31))
if self.value() == '90s':
return queryset.filter(birthday__gte=date(1990, 1, 1),
birthday__lte=date(1999, 12, 31))
class PersonAdmin(admin.ModelAdmin):
list_filter = (DecadeBornListFilter,)