今天遇到一个问题,用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