提高Django管理列表过滤器查询的性能

2024-10-03 09:18:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在围绕一个PostgreSQL数据仓库应用程序开发一个Django管理包装器,其中有些表包含数百万条记录。在

adminichangelist页面没有任何列表过滤器,可以在一秒钟内加载,但是如果我在管理员的list_filters中包含某些列,则加载速度非常慢,可能需要30秒到1分钟的时间来加载。在

在检查数据库时,我看到了以下几个查询:

SELECT DISTINCT "warehouse_data"."filter_field1" FROM "warehouse_data" ORDER BY "warehouse_data"."filter_field1" ASC;

每一个只需要3-5秒,但是有一打,这些加起来。所有的字段都被编入索引,所以我不知道如何才能加快速度。如何提高管理性能?如何插入Django的缓存机制来缓存这些列表过滤器的实际查询?在


Tags: django过滤器列表datapostgresql管理员记录页面
1条回答
网友
1楼 · 发布于 2024-10-03 09:18:32

正如您所观察到的那样,这种缓慢性来自于django编译惟一值的列表,以便可以在侧边栏中显示它们。在

实际上,这需要对数据库进行一次完整的表扫描,当表非常大时,这是非常昂贵的。如果您将此字段用作list_过滤器,那么唯一值的数量很可能很小,并且您可以更有效地自己生成唯一值列表(假设您知道这些值来自何处)。为此,您可以定义一个自定义列表过滤器。在

the docs(缩写为bereivity):

list_filter should be a list or tuple of elements, where each element should be of one of the following types:

  • a field name
  • a class inheriting from 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,)

相关问题 更多 >