flask-sqlalchemy的paginate源码分析

简介: 今天遇到一个问题,用flask-sqlalchemy的paginate做分页的时候,发现联表查询时分页出来结果数据少了很多,直接all()出来就没问题,把sql单独执行发现是联表查时有重复数据,group一下就好了,但是all()结果没有重复的,all()还给滤重了?而且paginate还是在滤重前做的limit,所以去重后结果就少了,而且还影响了total的值,趁这个机会看一下flask-sqlalchemy的源码吧

今天遇到一个问题,用flask-sqlalchemy的paginate做分页的时候,发现联表查询时分页出来结果数据少了很多,直接all()出来就没问题,把sql单独执行发现是联表查时有重复数据,group一下就好了,但是all()结果没有重复的,all()还给滤重了?而且paginate还是在滤重前做的limit,所以去重后结果就少了,而且还影响了total的值,趁这个机会看一下flask-sqlalchemy的源码吧

class BaseQuery(orm.Query):
    def paginate(self, page=None, per_page=None, error_out=True, max_per_page=None, count=True):
        """
        当“error_out”为"True"时,符合下面判断时将引起404响应,我一般都关了这个
        error_out,把接口返回什么的控制权拿回来。
        """
        //如果"page"或"per-page"是"None",则将从请求查询
        //flask-sqlalchemy和flask app绑定的还真是挺深,连request都用上了
        if request:
            if page is None:
                try:
                    //这么写更好page = request.args.get('page', 1, type=int)
                    page = int(request.args.get('page', 1))
                except (TypeError, ValueError):
                    if error_out:
                        abort(404)

                    page = 1

            if per_page is None:
                try:
                    per_page = int(request.args.get('per_page', 20))
                except (TypeError, ValueError):
                    if error_out:
                        abort(404)

                    per_page = 20
        else: // 如果没有请求分别默认为1和20
            if page is None:
                page = 1
            if per_page is None:
                per_page = 20
        //如果指定了“max_per_page”,则“per_page”将受这个值钳制。
        if max_per_page is not None:
            per_page = min(per_page, max_per_page)

        if page < 1:
            ......
                page = 1

        if per_page < 0:
            ......
                per_page = 20
        //原来paginate就是用的limit和offset,我猜如果有重复数据,先limit后all,all的时候再去个重,数据就少了,分页也没了
        items = self.limit(per_page).offset((page - 1) * per_page).all()
        ......
        //如果"count"是"False",total就不能用了,不用的时候可以关掉,省个查询
        if not count:
            total = None
        else:
            //为什么order_by(None)?
            total = self.order_by(None).count()

        return Pagination(self, page, per_page, total, items)

class Pagination(object):
    def __init__(self, query, page, per_page, total, items):
        #: the unlimited query object that was used to create this
        #: pagination object.
        self.query = query
        #: the current page number (1 indexed)
        self.page = page
        #: the number of items to be displayed on a page.
        self.per_page = per_page
        #: the total number of items matching the query
        self.total = total
        #: the items for the current page
        self.items = items
    ......

flask-sqlalchemy代码没有去重,再看看sqlalchemy的代码

class Query(Generative):
    ......
    def all(self):
        """
        不翻译了,留着原话,这里给去重了
        Return the results represented by this :class:`_query.Query`
        as a list.
        This results in an execution of the underlying SQL statement.
        .. warning::  The :class:`_query.Query` object,
           when asked to return either
           a sequence or iterator that consists of full ORM-mapped entities,
           will **deduplicate entries based on primary key**.  See the FAQ for
           more details.
            .. seealso::
                :ref:`faq_query_deduplicating`
        """
        return self._iter().all()
    ......

到此,可知sqlalchemy的all()操作是去重了的

参考
https://github.com/pallets/flask-sqlalchemy
https://github.com/sqlalchemy/sqlalchemy

相关文章
扒源码 - 一个请求在flask中经历了什么
客户端发起一个请求,Flask 都干了什么呢?url 如何与视图进行绑定的?
|
存储 小程序 关系型数据库
python微信小程序看图猜成语源码flask
启动Idiom/flask下的venv虚拟环境,运行python manage.py runserver命令启动Flask。然后打开微信开发者工具并扫码登录,选择flask/weapp-idiom小程序,加载完成后进入小程序登录页面,
240 0
|
Python
Flask 源码阅读-下篇 |Python 主题月
flask项目大名鼎鼎,不需要多做介绍。我把它称之为python服务开发的TOP2项目,另外一个就是django。这两个项目各有千秋,各自有不同的应用场景,都需要深入理解,熟练掌握。本次源码选择的版本是 1.1.2,我会采用慢读法,尽自己最大努力把它讲透。
193 0
|
Python
Flask 源码阅读-正菜 |Python 主题月
flask项目大名鼎鼎,不需要多做介绍。我把它称之为python服务开发的TOP2项目,另外一个就是django。这两个项目各有千秋,各自有不同的应用场景,都需要深入理解,熟练掌握。本次源码选择的版本是 1.1.2,我会采用慢读法,尽自己最大努力把它讲透。
161 0
|
Shell PHP 数据库
Flask 源码阅读-开胃菜
flask项目大名鼎鼎,应该不需要多做介绍了吧。我把它称之为python服务开发的TOP2项目,另外一个就是django了,不需要比较孰优孰劣,我的观点是各有千秋,各自应用于不同的场景,都需要深入理解,熟练掌握。本次源码选择的版本是 1.1.2,我会采用慢读法,尽自己最大努力把它讲透。本篇是开胃菜,主要分析flask的命令行工具的实现。
190 0
|
编解码 Python
Python 技术篇 - 修改源码解决中文主机名导致的flask、socket服务起不来问题: ‘utf-8‘ codec can‘t decode byte 0xc0 in position...
Python 技术篇 - 修改源码解决中文主机名导致的flask、socket服务起不来问题: ‘utf-8‘ codec can‘t decode byte 0xc0 in position...
395 0
Python 技术篇 - 修改源码解决中文主机名导致的flask、socket服务起不来问题: ‘utf-8‘ codec can‘t decode byte 0xc0 in position...
|
Python
Python Web Flask源码解读(一)——启动流程
Python Web Flask源码解读(一)——启动流程0x00 什么是WSGIWeb Server Gateway Interface它由Python标准定义的一套Web Server与Web Application的接口交互规范。
1379 0
|
Python Go 前端开发
源码解析flask的路由系统
当我们新建一个flask项目时,pycharm通常已经为项目定义了一个基本路由 @app.route('/') def hello_world(): return 'Hello World!' 此时在浏览器中输入地址http://127.
942 0
|
JSON 数据格式 Python
源码解析Flask的配置文件
在flask里,我们常在主文件中定义某些配置,比如: app.debug = True app.secret_key = 'helloworld!!' 实际上,flask中默认可以进行可选的配置项有很多。
978 0