28

I am having trouble implementing pagination with Flask-SQLAlchemy or Flask-Pagination, either or. I am unsure how to initialize the pagination, setting pages, determining pages, offest, etc. I am coming from PHP, quite new to Python.

I am querying all the posts in my database

posts = Posts.query.order_by(Posts.time.desc()).all()

I have been looking at the following examples:

I am confused on really what to do, the information I am finding greatly differs between articles. It's left me with confusion and not knowing where to begin. I want to query all rows of the database table, limit the results to 20 and paginate. I'm not seeing this clearly.

asked Mar 29, 2017 at 20:31

4 Answers 4

65

I recommend using Flask-SQLAlchemy's pagination: http://flask-sqlalchemy.pocoo.org/2.1/api/?highlight=pagination#flask.ext.sqlalchemy.Pagination

There's a well-written example here: https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-ix-pagination

Here's the basic idea for the view:

@app.route('/myview/<int:page>',methods=['GET'])
def view(page=1):
 per_page = 10
 posts = Posts.query.order_by(Posts.time.desc()).paginate(page,per_page,error_out=False)
 return render_template('view.html',posts=posts)

And then for the template (I don't know your posts model so I made something up):

<html>
 <head>
 Posts
 </head>
 <body>
{% for post in posts.items %}
<p>
 {{ post.post_name }} post body: <b>{{ post.body }}</b>
</p>
{% endfor %}
{% if posts.has_prev %}<a href="{{ url_for('view', page=posts.prev_num) }}">&lt;&lt; Newer posts</a>{% else %}&lt;&lt; Newer posts{% endif %} | 
{% if posts.has_next %}<a href="{{ url_for('view', page=posts.next_num) }}">Older posts &gt;&gt;</a>{% else %}Older posts &gt;&gt;{% endif %}
 </body>
</html>
answered Mar 29, 2017 at 21:55
Sign up to request clarification or add additional context in comments.

7 Comments

Minor change required - @app.route('/myview/', methods=['GET'], defaults={"page": 1}) @app.route('/myview/<int:page>',methods=['GET']) def view(page):
How to accept the sort column name and order (asc/desc) as query parameters? My UI view has controls on each column head to permit sorting on that column, ascending or descending. Makes a big difference for pagination results :)
@chrisinmtown: probably worth it's own question! Or you can just look at the many questions already about this! Here's one: stackoverflow.com/questions/24892035/…
Sorry, poor wording. Should have written "How to pass sort column and order (asc/desc) strings from query parameters to the order_by() method?"
@chrisinmtown: oh, I really don't think that method accepts an argument for that. You can have an if block to handle. For example, if args.sort_order == 'desc': # do something here, and you get the idea.
6

Controller

@app.route('/', methods=['GET'], defaults={"page": 1}) 
@app.route('/<int:page>', methods=['GET'])
def index(page):
 page = page
 per_page = 2
 users = User.query.paginate(page,per_page,error_out=False)
 # print("Result......", users)
 return render_template("index.html", users=users)

in the View

{% for user in users.items %}
 <h1> {{ user.name }} </h1>
{% endfor %}
<nav aria-label="Page navigation example">
 <ul class="pagination">
 {% if users.has_prev %}
 <li class="page-item"> <a class="page-link" href="{{ url_for('index', page=users.prev_num) }}">Previous</a></li>
 {% else %}
 <li class="page-item"><a class="page-link btn disabled" href="#">Previous</a></li>
 {% endif %}
 {% if users.has_next %}
 <li class="page-item"> <a class="page-link" href="{{ url_for('index', page=users.next_num) }}">Next</a></li>
 {% else %}
 <li class="page-item"><a class="page-link btn disabled" href="#">Next</a></li>
 {% endif %}
 </ul>
 </nav>
answered Aug 4, 2019 at 17:05

Comments

3

I used @user3186184 code but I got this error:

TypeError: 'Pagination' object is not iterable

But when I add items to the end of these code:

users = User.query.paginate(page,per_page,error_out=False).items

My issue was fixed.

answered Feb 28, 2022 at 6:06

Comments

-1

Here is the simplest answer to add pagination in flask

no_of_posts = 3
page = request.args.get("number")
 if page is None:
 page = 1
 else:
 page = int(page)
 allPosts = Posts.query.filter_by().all()
 length = len(allPosts)
 allPosts = allPosts[(page-1)*no_of_posts: page*no_of_posts]
 if page > 1:
 prev = page -1
 else:
 prev = None
 if page < math.ceil(length/no_of_posts):
 next = page + 1
 else:
 next = None

In the template

{% if prev %}
<a href="?number={{ prev }}">&laquo; Previous</a>
{% endif %}
{% if next %}
<a href="?number={{ next }}">Next &raquo;</a>
{% endif %}
answered Dec 14, 2021 at 3:14

1 Comment

While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.