分页的目的
做个假设,加入用例库有 1W 条数据,如果想要以列表形式展示,一次性返回 1W 条数据;
这样做有两个弊端:
1.这样写出来的接口会慢。想一下如果随着时间的发展,这个数量变成了 10W、100W 该怎么办?
2.对前端不友好。用前端渲染 1W 条数据,有理智的开发都不会这么做。
所以,我们做分页的目的,主要是为了性能的提高,提高使用体验。
我这边开发语言是Python,Web框架用的是 Tornado,后台数据库用的是 Mongodb。
接口设计
首先,我们做一下接口的设计,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
HTTP URL: / api / admin / v1 / case / list
HTTP Method: GET
Request Params
Reponse Data
{
"code" : 0 ,
"message" : null,
"data" : {
"cases" : [
{
"method" : str ,
"url" : str ,
"request_data" ?: str ,
"request_params" ?: str ,
"header" : dict ,
"reponse_data" ?: str
},
...
],
"count" : int
}
}
|
返回数据结构解析:
- cases 的值是包含多个 case 对象的列表;
- count 指的是 case 的总数,这样前端就可以通过 count 来判断一共有多少页,然后通过点击的页数直接请求到对应页的数据做展示,这样做可以有效的控制返回的数据量以及返回时间,提高用户体验感。
根据上述的接口约定,接口实现如下(仅展示关键代码):
1
2
3
4
5
6
7
8
9
10
|
class CaseList(APIHandler):
async def get_handler( self ):
page = self . input .page or 1
limit = self . input .limit or 12
page, limit = int (page), int (limit)
skip = limit * (page - 1 )
return {
'customers' : await CaseService.get_case_list(filter_ = {}, skip = skip, limit = limit),
'count' : await CaseService.get_count(filter_ = {})
}
|
接口解读
下面我们逐行来解读这个接口。
1.根据 API 约定,page和limit是不必传且有默认值,所以获取时可以直接写为self.input.page or 1,其中当page不传时self.input.page为None。
2.后端获取到的GET请求的请求参数是String,所以需要int()转为整型,这里直接int(page)即可,因为经过了前面的处理,page必然是有值的。
3.通过limit * (page - 1),计算出跳过多少个;白话描述skip的作用就是,从第skip个对象开始,往后取limit个,返回。
4.get_case_list方法和get_count方法的filter_参数的值应该保持一致,因为他们都是对case这个对象做操作,只不过count是取总数而已。
CaseService.get_case_list方法
1
2
3
4
5
6
7
8
|
async def get_case_list(filter_: dict , skip: int = None , limit: int = None ) - > Optional[ List [ dict ]]:
""" 获取 case 列表 """
sort = [( 'create_time' , - 1 )]
if skip is not None and limit is not None :
ret = await cls .find( 'case' , filter = filter_, sort = sort, limit = limit, skip = skip)
else :
ret = await cls .find( 'case' , filter = filter_, sort = sort)
return ret
|
1.对skip和limit的空值判断要用is not None,因为skip可能为,如果使用if skip来判断,skip=0的时候也会进入分支。
2.sort = [(‘create_time', -1)]的传入使返回的列表按照创建时间倒叙排列,如果你不做这个,相信负责人的测试同学会给你提一个“易用性问题”。
3.sort + skip + limit是有执行优先级的,他们优先级依次是sort→skip→limit,skip+limit的优先级为skip→limit。
这里大家不要去考虑pymogo执行的时候会不会对sort、skip、limit自动给按照优先级执行,传参的时候按照优先级去传参就好了,养成良好的习惯,不必纠结其他的。
CaseService.get_count方法
1
2
3
|
async def get_count( cls , filter_: dict ) - > int :
""" 获取 case 总数 """
return await ModelHandler.count( 'case' , filter = filter_)
|
这里用count来获取数据,可以直接拿到总数,而不是取出list然后去求length,避免了内存空间的浪费。
以上,就是对列表接口进行分页的整个过程啦,谢谢阅读,这不是一篇喂饭教程,是带你熟悉了写这个接口的整个过程及其中的细节,具体的实现还需要大家动手去实践。
以上就是Python优化列表接口进行分页示例实现的详细内容,更多关于Python优化的资料请关注服务器之家其它相关文章!
原文链接:https://blog.csdn.net/AI_Green/article/details/120511875