大家好!
我们都知道Django管理员是Django的超酷工具。 您可以检查模型,并从表中添加/编辑/删除记录。 如果您熟悉Django,我相信您已经知道了。
我得到了一个任务:我们的客户想按一个字段在一个表中搜索。 看起来很容易,对吧? 好吧,棘手的部分是该表具有523.803.417记录。
哇。 523.803.417条记录。
至少模型不是那么复杂:
在models.py上:
1 2 3 4 5 6 7 |
class HugeTable(models.Model): """Huge table information""" search_field = models.CharField(max_length=10, db_index=True, unique=True) is_valid = models.BooleanField(default=True) def __str__(self): return self.search_field |
因此,对于Django管理员而言,应该轻而易举,对吗? 错误。
过程
首先,我只是在admin.py上添加了搜索字段:
在admin.py上:
1 2 3 4 |
class HugeTableAdmin(admin.ModelAdmin): search_fields = ('search_field', ) admin.site.register(HugeTable, HugeTableAdmin) |
而且有效! 我的管理员有一个有效的搜索字段。
唯一的问题:加载页面需要3分钟以上的时间,而搜索则需要5分钟以上的时间。 但是至少它在起作用,对吗?
WTF?
首先,让我们分解问题:
为什么只花了3分钟来加载页面?
如果搜索字段已被索引,为什么要花+5分钟的时间进行搜索?
我开始处理第一个记录,并发现它很容易:Django一次只获取100条记录,但是它必须计算分页器的长度和搜索栏上的“查看更多”按钮
改善页面加载
快速浏览Django文档,告诉我如何停用“查看更多”查询:
ModelAdmin.show_full_result_count
设置show_full_result_count以控制是否应在过滤后的管理页面上显示对象的总数(例如99个结果(共103个结果))。 如果此选项设置为False,则会显示类似99结果(显示全部)的文本。
On admin.py
:
1 2 3 4 5 |
class HugeTableAdmin(admin.ModelAdmin): search_fields = ('search_field', ) show_full_result_count = False admin.site.register(HugeTable, HugeTableAdmin) |
那解决了一个问题,但是另一个问题呢? 看来我需要做分页器。
值得庆幸的是,我发现Haki Benita撰写了一篇很棒的帖子,名为“ Optimize the Django Admin Paginator”,对此做了确切的解释。 由于不需要知道记录数,因此我采用了“哑巴”方法:
在admin.py上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from django.core.paginator import Paginator from Django.utils.functional import cached_property class DumbPaginator(Paginator): """ Paginator that does not count the rows in the table. """ @cached_property def count(self): return 9999999999 class HugeTableAdmin(admin.ModelAdmin): search_fields = ('search_field', ) show_full_result_count = False paginator = DumbPaginator admin.site.register(HugeTable, HugeTableAdmin) |
而且有效! 该页面加载非常快:)但是搜索仍然非常慢。 因此,让我们对其进行修复。
改善搜寻
我检查了很多选项。 我几乎和Haystack一起去了,但是对于我所需要的东西似乎有些过高了。 我终于找到了这个超级酷的工具:djangoql。 它允许我使用类似sql的操作来搜索表,因此我可以通过search_field进行搜索并利用索引。 所以我安装了它:
在settings.py上:
1 2 3 4 5 |
INSTALLED_APPS = [ ... 'djangoql', ... ] |
On admin.py
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from django.core.paginator import Paginator from django.utils.functional import cached_property from djangoql.admin import DjangoQLSearchMixin class DumbPaginator(Paginator): """ Paginator that does not count the rows in the table. """ @cached_property def count(self): return 9999999999 class HugeTableAdmin(DjangoQLSearchMixin, admin.ModelAdmin): show_full_result_count = False paginator = DumbPaginator admin.site.register(HugeTable, HugeTableAdmin) |
而且有效! 通过执行查询:
1 |
search_field = "my search query" |
我大约1秒钟就能得到结果。
好了吗?
是! 现在,我的客户可以非常轻松,非常快速地通过search_field在523.803.417记录的表上进行搜索。
我打算通过与此客户端一起发布更多我正在学习的Python / Django知识,因此您可能希望保持关注
原文:https://blog.rogs.me/2020/02/17/how-to-search-in-a-huge-table-on-django-admin/