如何优化Django的分页模块

2 投票
2 回答
1309 浏览
提问于 2025-04-16 09:25

我有个问题想问关于Django的分页模块是怎么工作的,以及怎么优化它。我有大约300个项目的信息,这些信息是我从网上不同的API获取的。我正在使用Django的分页模块来给我的访客展示这个列表,每次显示10个项目。但是分页的效果没有我想象的那么好。看起来这个分页器在每次切换页面时,都需要先获取所有300个项目,然后再从中抽取出需要显示的10个。例如,如果有30页,那么要跳到第2页,就需要我的网站再次查询API,把所有信息放到一个列表里,然后再取出访客浏览器请求的那10个。我不想在每次翻页时都去查询那些我已经有的信息。

现在,我的视图里有一个函数,它会查看请求,然后根据请求去查询API获取信息。然后它把所有这些信息放到一个列表里,再传递给模板文件。所以,每当有人翻页时,这个函数总是会被加载,导致又一次查询API。

我该怎么解决这个问题呢?

谢谢你的帮助。

2 个回答

0

ORM(对象关系映射)在选择行之前不会加载数据:

query_results = Foo(id=1) # No sql executed yet, just stored.

foo = query_results[0] # now it fires

或者

for foo in query_results:
   foo.bar() # sql fires

如果你使用的是一个自定义的数据源,并且在初始化时就加载了所有结果,那么分页功能可能就不能正常工作,因为所有的数据会一次性被获取。你可能需要重写 __getitem____iter__ 方法来进行实际的数据获取。这样做就能和Django期望的结果加载方式相匹配。

分页需要知道有多少个结果,这样才能判断是否还有下一页(has_next())。在SQL中,获取 count(*) 的操作通常是比较便宜的,尤其是有索引的情况下。因此,你也需要知道会有多少个结果(如果确切知道太贵的话,可能只需要估算一下)。

1

在这种情况下,分页器需要完整的列表才能正常工作。

我的建议是定期更新一次数据的缓存,然后用这个缓存作为分页器的输入。每次请求都去做一些耗时的工作是个坏主意。想想用户加载页面时的体验,还有你的服务器可能会受到攻击的风险。

你可以看看 Django的低级缓存API,它可以让你把数据结果存储在一个全局可访问的地方,用一个键来标识,之后你就可以用这个键来取出缓存,并为每个页面请求进行分页。

撰写回答