flask-sqlalchemy icon indicating copy to clipboard operation
flask-sqlalchemy copied to clipboard

Revisit Pagination

Open immunda opened this issue 9 years ago • 12 comments

Devise a more extensible solution which deals with the issues raised in #232, #281, #265, #151 & #70

immunda avatar Apr 24 '15 16:04 immunda

I put some thoughts into #272, and think it is worth to mention here. OFFSET is not the best way to paginate. It was also noticed by @noah in https://github.com/mitsuhiko/flask-sqlalchemy/issues/232#issuecomment-76480428. So, I like to join discussion.

xen avatar Apr 27 '15 13:04 xen

Something I didn't find mentioned directly in the other pagination issue reports is that db.session does not use the same query class as db.Model.query. This is trivial to solve by passing query_cls, but it's a weird oversight that can cause confusion. For example, db.session.query(thing1, thing2).paginate() doesn't work.

from flask_sqlalchemy import SQLAlchemy, BaseQuery
db = SQLAlchemy(session_options={'query_cls': BaseQuery})

davidism avatar Jun 12 '15 16:06 davidism

Making a note here that db.session now uses the same query class as db.Model.query by default as of #328 :dancer:

immunda avatar Dec 04 '15 14:12 immunda

I am sure I am using flask_sqlalchemy, but "AttributeError: 'list' object has no attribute 'paginate'" happens. so upset!

wck821829906 avatar Apr 17 '17 02:04 wck821829906

@wck821829906: Don't call .all() before calling .paginate(). Also, don't hijack unrelated issues.

ThiefMaster avatar Apr 17 '17 02:04 ThiefMaster

Has there been any progress on this issue? I am not at all an SQL expert, otherwise I would try to tackle it ...

sebpiq avatar Jun 08 '17 09:06 sebpiq

COUNT is super slow, and Flask-SQLAlchemy always gets COUNT for pagination. The first step would be to stop using COUNT and just have prev/next based pagination. Since this project looks dead, we just have to create our own implementations.

patrickyan avatar Sep 03 '17 22:09 patrickyan

Hi Patrick, this project is not dead. I'd be happy to review any work you're willing to put into pull requests, but have limited free time to devote to this myself at the moment. Thank you.

davidism avatar Sep 03 '17 23:09 davidism

As to the count stuff, this comes up every now and then, search back through the closed issues for an explanation. I don't plan to remove it.

davidism avatar Sep 03 '17 23:09 davidism

There are many cases where COUNT and OFFSET are perfectly fine. Unless you are above ten thousands of rows in the initial resultset you can safely use them. And honestly, most typical webapps using flask-sqlalchemy's pagination are not that likely to end up having to paginate that many rows.

If you need something more efficient (usually prev/next based on WHERE indexed-column > prev-value LIMIT x and similar approaches writing your own implementation is easy.

ThiefMaster avatar Sep 03 '17 23:09 ThiefMaster

Maybe using window functions might improve performance here? I noticed that (at least for us and using postgres), counting through window functions results in faster queries (tested for tables with around 10 million rows and especially queries containing joins).

A query like

SELECT foo.*, count(*) OVER () AS total
FROM mytable
ORDER BY somecolumn DESC;

performs way better than two distinct queries

SELECT foo.*
FROM mytable
ORDER BY somecolumn DESC
LIMIT 20
OFFSET 0;

SELECT count(*)
FROM mytable

I am, however, not sure how to implement this in a generic way to include the total count when querying the relevant items.

Birne94 avatar Nov 23 '18 15:11 Birne94

This may be way out in left field but...should we consider removing pagination from Flask-SQLAlchemy? My brief thought is that FSA is a bridge between Flask and SQLAlchemy. Pagination seems like a separate concern. Is there anything that requires Pagination to be embedded in the library as opposed to maintained in a separate library (assuming someone wanted to do that)?

I bring this up mostly due to the maintenance burden of having additional code in the library. As I went through the issues today, there were a decent number of them that touched on pagination. I'd personally rather see core FSA get more love and bump this out to a separate library (or just deprecate and then eventually remove it and let someone else build the library if they want to maintain it separate from FSA).

rsyring avatar Mar 08 '19 18:03 rsyring

#1087 addressed some pagination issues, I'm fine with continuing to support it.

The query interface is legacy in SQLAlchemy 2.0, I'll be adding some support for select() instead.

davidism avatar Sep 18 '22 17:09 davidism

In #1100 I ended up removing creating Pagination objects manually as a public API. I think supporting pagination makes sense, it's a very common interface in web applications, but I also don't think we need to provide a generic pagination API. So now db.paginate and query.paginate are the only ways to get pagination in the public API.

davidism avatar Sep 24 '22 16:09 davidism