Python Optimized List Interface for Paging Sample Implementation
- 2021-12-04 19:13:32
- OfStack
Purpose of paging
Let's assume that there are 1W pieces of data added to the use case library. If you want to show them in the form of a list, return 1W pieces of data once;
This has two drawbacks:
1. The interface written in this way will be slow. Think about what should I do if this number becomes 10W and 100W with the development of time?
2. Unfriendly to the front end. Render 1W pieces of data with the front end, which would not be done by rational development.
Therefore, the purpose of paging is mainly to improve performance and experience.
My side of the development language is Python, Web framework is Tornado, the background database is Mongodb.
Interface design
First of all, we do the design of the interface as follows:
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
}
}
Returns data structure parsing:
The value of cases is a list containing multiple case objects; count refers to the total number of case, so that the front end can judge how many pages there are in 1 through count, and then directly request the data of the corresponding page for display through the number of pages clicked, which can effectively control the amount of data returned and the return time, and improve the user experience.According to the above interface convention, the interface implementation is as follows (only the key code is shown):
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_={})
}
Interface interpretation
Let's read this interface line by line.
1. According to the API convention, page and limit do not need to be transmitted and have default values, so they can be directly written as self. input. page or 1, where self. input. page is None when page is not transmitted.
2. The request parameter of GET request obtained by the back end is String, so int () needs to be converted into integer type. Here, int (page) can be directly used, because after the previous processing, page must have a value.
3. Calculate how many are skipped by limit * (page-1); The function of skip described in vernacular is to start with the first skip object, take the next limit and return.
4. The value of the filter_ parameter of the get_case_list method and the get_count method should be kept at 1, because they both operate on the case object, except that count is a total.
CaseService.get_case_list method
async def get_case_list(filter_: dict, skip: int = None, limit: int = None) -> Optional[List[dict]]:
""" Get case List """
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. To judge the null value of skip and limit, use is not None, because skip may be, and if if skip is used to judge, skip = 0 will also enter the branch.
2. The incoming of sort = [('create_time',-1)] causes the returned list to be arranged flashback according to the creation time. If you don't do this, I believe the test classmates in charge will ask you a "usability question".
3. sort + skip + limit have execution priority, and their priority is sort → skip → limit, and the priority of skip + limit is skip → limit.
Here, we should not consider whether sort, skip and limit will be automatically executed according to the priority when pymogo is executed. When transmitting parameters, it is good to transmit parameters according to the priority, so as to develop good habits and not worry about others.
CaseService.get_count method
async def get_count(cls, filter_: dict) -> int:
""" Get case Total """
return await ModelHandler.count('case', filter=filter_)
Here use count to get data, you can get the total directly, instead of taking out list and then seeking length, avoiding the waste of memory space.
The above is the whole process of paging the list interface. Thank you for reading. This is not a feeding tutorial. It takes you familiar with the whole process of writing this interface and its details. The specific implementation needs everyone to practice.
The above is the Python optimization list interface for paging sample implementation details, more information about Python optimization please pay attention to other related articles on this site!