Issue
I have been looking for an answer for a long time how to implement pagination on the site, I use only Python and its frameworks. Is it even possible to do this? If so, how to use the jinja template engine to create a new page automatically with ten or more discussion elements. If there is no python solution, then I would really like to know how to implement it through js along with html in order to at least understand the mechanics.
html
{% for discussion in discussions_json %}
<a style="font-size: 19px; margin-right: auto; width: 88%; color:white; text-decoration:none; " href="/community/discussion/{{ discussion.id }}">{{ discussion.title }}</a> <span style="font-size: 25px; float: right; color: #0abab5;">{{ discussion.date.strftime("%H:%M | %d.%m.%Y") }}</span>
<p style="font-size: 19px; margin-right: auto; width: 88%; color: red;">@{{ discussion.username }}</p>
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-chat-dots-fill" viewBox="0 0 16 16">
<path d="M16 8c0 3.866-3.582 7-8 7a9 9 0 0 1-2.347-.306c-.584.296-1.925.864-4.181 1.234-.2.032-.352-.176-.273-.362.354-.836.674-1.95.77-2.966C.744 11.37 0 9.76 0 8c0-3.866 3.582-7 8-7s8 3.134 8 7M5 8a1 1 0 1 0-2 0 1 1 0 0 0 2 0m4 0a1 1 0 1 0-2 0 1 1 0 0 0 2 0m3 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2"/>
</svg>
<span> {{ discussion.answer_count }}</span>
<hr />
{% endfor %}
python
@blueprint.route('/community')
def community_page():
discussions_json = []
discussions_list = Discussions.query.filter(Discussions.title.isnot(None)).order_by(Discussions.date.desc()).all()
for discussion in discussions_list:
discussions_json.append(
{
"id": discussion.id,
"title": discussion.title,
"text": discussion.text,
"date": discussion.date,
"username": User.query.filter_by(id=discussion.autor).first().username,
"answer_count": discussion.answer_count()
}
)
return render_template("community.html", discussions_json=discussions_json)
Solution
The following example shows you how you can implement pagination with the Flask-SQLAlchemy legacy API you are using.
Instead of a request with a final all()
, the command paginate(page=None, per_page=None, error_out=True, max_per_page=None)
is used. It is then possible to add navigation for all available pages in the template. In the example this is achieved using a jinja macro. The database entries that were previously available directly are now accessible via the items
attribute of the pagination object.
from flask import (
Flask,
render_template,
request
)
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import func
from sqlalchemy.ext.associationproxy import association_proxy
app = Flask(__name__)
app.config.from_mapping(
SQLALCHEMY_DATABASE_URI='sqlite:///example.db'
)
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, nullable=False, unique=True)
# ...
discussions = db.relationship('Discussion', backref='author')
class Discussion(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
text = db.Column(db.Text)
date = db.Column(db.DateTime,
nullable=False,
server_default=func.now())
author_id = db.Column(db.Integer,
db.ForeignKey('user.id'),
nullable=False)
# ...
username = association_proxy('author', 'username')
with app.app_context():
db.drop_all()
db.create_all()
user = User(username='dummy')
db.session.add(user)
discussions = [
Discussion(
author=user,
title=f'Title-{i}',
text='Your text here!'
)
for i in range(1, 21)
]
db.session.add_all(discussions)
db.session.commit()
@app.route('/community')
def community_page():
per_page = 5
page = request.args.get('page', 1, type=int)
discussions = Discussion.query\
.filter(Discussion.title.isnot(None))\
.order_by(Discussion.date.desc())\
.paginate(page=page, per_page=per_page)
return render_template('community.html', **locals())
# ...
{% 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 %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Community</title>
</head>
<body>
{% for discussion in discussions.items -%}
<a href="/community/discussion/{{ discussion.id }}">{{ discussion.title }}</a>
<span>{{ discussion.date.strftime("%H:%M | %d.%m.%Y") }}</span>
<p>@{{ discussion.username }}</p>
<hr />
{% endfor -%}
{{ render_pagination(discussions, request.endpoint) }}
</body>
</html>
If you are interested in how pagination can be implemented with the latest query variant, I recommend this article.
Answered By - Detlef
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.