Flask中,用Flask-Restful去设计api
现在遇到一个,需要实现分页的接口
想要搞清楚,一般设计这种接口的逻辑是啥
直接从数据库query后,然后根据当前的page数,返回结果即可?
Flask-restful 分页 api
可以借鉴这个:
{
“page”: 1, # 当前是第几页
“pages”: 3, # 总共多少页
“per_page”: 10, # 每页多少数据
“has_next”: true, # 是否有下一页数据
“has_prev”: false, # 是否有前一页数据
“total”: 27 # 总共多少数据
}
使用 Flask-RESTful 设计 RESTful API — Designing a RESTful API with Python and Flask 1.0 documentation
RESTful API 设计最佳实践 – 文章 – 伯乐在线
flask restful pagination
Customizing the ReSTful interface — Flask-Restless 0.17.0 documentation
flask-restful/paging.py at master · flask-restful/flask-restful
HATEOAS support for pagination on server side · Issue #60 · flask-restful/flask-restful
web services – RESTful Design: Paging Collections – Stack Overflow
Flask REST api resource URLs suggestions – Stack Overflow
flask restful paging
The Flask Mega-Tutorial, Part IX: Pagination – miguelgrinberg.com
flask_restful.paging.retrieve_next_page – Nullege Python Samples
The Flask Mega-Tutorial, Part IX: Pagination – miguelgrinberg.com
-》
posts = g.user.followed_posts().paginate(1, 3, False).items
-》
看来是:
Flask-SQLAlchemy支持的paginate,所以去搜:
Flask-SQLAlchemy page
Flask-SQLAlchemy paging
在flask-sqlalchemy中使用分页 – ranvane的个人空间 – 开源中国社区
API — Flask-SQLAlchemy Documentation (2.1)
http://flask-sqlalchemy.pocoo.org/2.1/api/
paginate(page=None, per_page=None, error_out=True) Returns per_page items from page page. By default it will abort with 404 if no items were found and the page was larger than 1. This behavor can be disabled by setting error_out to False. If page or per_page are None, they will be retrieved from the request query. If the values are not ints and error_out is true, it will abort with 404. If there is no request or they aren’t in the query, they default to page 1 and 20 respectively. Returns an Pagination object. Utilities class flask.ext.sqlalchemy.Pagination(query, page, per_page, total, items) Internal helper class returned by BaseQuery.paginate(). You can also construct it from any other SQLAlchemy query object if you are working with other libraries. Additionally it is possible to pass None as query object in which case the prev() and next() will no longer work. has_next True if a next page exists. has_prev True if a previous page exists items = None the items for the current page iter_pages(left_edge=2, left_current=2, right_current=5, right_edge=2) Iterates over the page numbers in the pagination. The four parameters control the thresholds how many numbers should be produced from the sides. Skipped page numbers are represented as None. This is how you could render such a pagination in the templates: {% macro render_pagination(pagination, endpoint) %} <div class=pagination> {%- for page in pagination.iter_pages() %} {% if page %} {% if page != pagination.page %} <a href=”{{ url_for(endpoint, page=page) }}”>{{ page }}</a> {% else %} <strong>{{ page }}</strong> {% endif %} {% else %} <span class=ellipsis>…</span> {% endif %} {%- endfor %} </div> {% endmacro %} next(error_out=False) Returns a Pagination object for the next page. next_num Number of the next page page = None the current page number (1 indexed) pages The total number of pages per_page = None the number of items to be displayed on a page. prev(error_out=False) Returns a Pagination object for the previous page. prev_num Number of the previous page. query = None the unlimited query object that was used to create this pagination object. total = None the total number of items matching the query |
[AF][Flask-SQLAlchemy] Pagination:flask
【总结】
然后此处,参考了:
API — Flask-SQLAlchemy Documentation (2.1)
最后写成:
<code> curPageTaskList = None # for debug taskPagination = None if curRole == UserRole.Initiator: taskPagination = Task.query.filter_by(initiatorId=userId).paginate( page=curPageNum, per_page=numPerPage, error_out=False) elif curRole == UserRole.Errandor: taskPagination = Task.query.filter_by(errandorId=userId).paginate( page=curPageNum, per_page=numPerPage, error_out=False) gLog.debug("type(taskPagination)=%s" ",taskPagination=%s" ",has_next=%s" ",has_prev=%s" # ",items=%s" # ",next()=%s" # ",next_num=%s" ",page=%s" ",pages=%s" ",per_page=%s" # ",prev_num=%s" # ",query=%s" ",total=%s", type(taskPagination), taskPagination, taskPagination.has_next, taskPagination.has_prev, # taskPagination.items, # taskPagination.next(error_out=False), # taskPagination.next_num, taskPagination.page, taskPagination.pages, taskPagination.per_page, # taskPagination.prev_num, # taskPagination.query, taskPagination.total ) # gLog.debug("type(taskPagination)=%s,taskPagination=%s", type(taskPagination), taskPagination) # type(taskPagination)=<class 'flask_sqlalchemy.Pagination'>, taskPagination=<flask_sqlalchemy.Pagination object at 0x7f07b83c7950> paginatedTaskList = taskPagination.items # gLog.debug("type(paginatedTaskList)=%s, paginatedTaskList=%s", type(paginatedTaskList), paginatedTaskList) paginatedTaskDict = {} for curIdx, eachTask in enumerate(paginatedTaskList): # gLog.debug("[%s] eachTask=%s", curIdx, eachTask) gLog.debug("[%s] eachTask.id=%s", curIdx, eachTask.id) paginatedTaskDict[eachTask.id] = marshal(eachTask, task_fields) respPaginatedTaskInfoDict = { "curPageNum" : taskPagination.page, "totalPageNum" : taskPagination.pages, "numPerPage" : taskPagination.per_page, "hasPrev" : taskPagination.has_prev, "hasNext" : taskPagination.has_next, "totalTaskNum" : taskPagination.total, 'tasks' : paginatedTaskDict } gLog.debug("respPaginatedTaskInfoDict=%s", respPaginatedTaskInfoDict) </code>
某次的输出的效果是:
[2016-11-09 14:33:14,533 DEBUG User.py:541 get] type(taskPagination)=<class ‘flask_sqlalchemy.Pagination’>,taskPagination=<flask_sqlalchemy.Pagination object at 0x7f78b6847890>,has_next=False,has_prev=True,page=2,pages=2,per_page=10,total=14 [2016-11-09 14:33:14,533 DEBUG User.py:553 get] [0] eachTask.id=task-10b01105-ec53-41bb-810e-720ab468bdf7 [2016-11-09 14:33:14,560 DEBUG User.py:553 get] [1] eachTask.id=task-f3c0c660-e7f5-4583-bab2-23c7006dadc4 [2016-11-09 14:33:14,582 DEBUG User.py:553 get] [2] eachTask.id=task-f7a4d0df-3142-444b-a962-83660acd447f [2016-11-09 14:33:14,599 DEBUG User.py:553 get] [3] eachTask.id=task-da013992-e7aa-4ae9-8b6f-bdf621b9fbaa [2016-11-09 14:33:14,615 DEBUG User.py:566 get] respPaginatedTaskInfoDict={‘tasks’: {u’task-da013992-e7aa-4ae9-8b6f-bdf621b9fbaa’: OrderedDict([(‘hasEnded’, True), (‘itemType’, ‘Small’), (‘initiatorEndLocation’, OrderedDict([(‘fullStr’,。。。。。 。。。。 , (‘password’, None), (‘id’, None), (‘createdAt’, None), (‘errandorIsAuthenticated’, None)]))])}, ‘hasNext’: False, ‘totalPageNum’: 2, ‘hasPrev’: True, ‘numPerPage’: 10, ‘curPageNum’: 2, ‘totalNum’: 14L} |
返回的json是:
{
“code”: 200,
“data”: {
“curPageNum”: 2,
“hasNext”: false,
“hasPrev”: true,
“numPerPage”: 10,
“tasks”: {
“task-10b01105-ec53-41bb-810e-720ab468bdf7”: {。。。},
“task-da013992-e7aa-4ae9-8b6f-bdf621b9fbaa”: {。。。},
“task-f3c0c660-e7f5-4583-bab2-23c7006dadc4”: {。。。},
“task-f7a4d0df-3142-444b-a962-83660acd447f”: {。。。}
},
“totalNum”: 14,
“totalPageNum”: 2
},
“message”: “get task/orders ok”
}
注:
此处的prev()有个bug,需要注意去规避:
对于上述的核心代码:
<code>taskPagination = Task.query.filter_by(errandorId=userId).paginate( page=curPageNum, per_page=numPerPage, error_out=False) </code>
的具体解释:
1.query对象,可以去通过paginate得到一个Pagination的对象
比如:
<code>Task.query.filter_by(errandorId=userId) </code>
得到的就是query对象
然后通过调用paginate,即可得到对应的Pagination对象
<code>type(taskPagination)=<class 'flask_sqlalchemy.Pagination'>,taskPagination=<flask_sqlalchemy.Pagination object at 0x7f78b6847890> </code>
2.Pagination的对象中,最常用到的属性就是:
items:具体有多少个对象,是个列表
然后就可以通过items去获取每个对象的详细信息了。
其他还有一些常用属性:
page:当前的页数
pages:总的页数
per_page:每一页的个数
has_prev:是否有前一页
has_next:是否有后一页
total:(符合当前分页查询的)总(的项目的)个数
转载请注明:在路上 » 【已解决】Flask-Restful中如何设计分页的API