阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Python如何优化列表接口进行分页

85次阅读
没有评论

共计 2247 个字符,预计需要花费 6 分钟才能阅读完成。

导读 最近,在做测试开发平台的时候,需要对测试用例的列表进行后端分页,在实际去写代码和测试的过程中,发现这里面还是有些细节的,故想复盘一下

Python 如何优化列表接口进行分页

分页的目的

做个假设,加入用例库有 1W 条数据,如果想要以列表形式展示,一次性返回 1W 条数据;

这样做有两个弊端:

1. 这样写出来的接口会慢。想一下如果随着时间的发展,这个数量变成了 10W、100W 该怎么办?

2. 对前端不友好。用前端渲染 1W 条数据,有理智的开发都不会这么做。

所以,我们做分页的目的,主要是为了性能的提高,提高使用体验。

我这边开发语言是 Python,Web 框架用的是 Tornado,后台数据库用的是 Mongodb。

接口设计

首先,我们做一下接口的设计,如下:

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 来判断一共有多少页,然后通过点击的页数直接请求到对应页的数据做展示,这样做可以有效的控制返回的数据量以及返回时间,提高用户体验感。

根据上述的接口约定,接口实现如下(仅展示关键代码):

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 方法
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 方法
async def get_count(cls, filter_: dict) -> int:
    """获取 case 总数"""
    return await ModelHandler.count('case', filter=filter_)

这里用 count 来获取数据,可以直接拿到总数,而不是取出 list 然后去求 length,避免了内存空间的浪费。

以上,就是对列表接口进行分页的整个过程啦,谢谢阅读,这不是一篇喂饭教程,是带你熟悉了写这个接口的整个过程及其中的细节,具体的实现还需要大家动手去实践。

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-25发表,共计2247字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中