如何用Python框架结合Jinja实现网站分页?附JS+HTML方案
完全可以用Python结合Flask和Jinja实现分页,下面分两种方案说明,优先推荐后端分页(性能更优):
一、Python + Flask + Jinja 后端分页方案
后端分页不会一次性加载所有数据,适合数据量大的场景,核心是用SQLAlchemy的paginate方法实现数据库层面的分页查询。
1. 修改后端路由代码
接收前端传入的页码参数,替换全量查询为分页查询:
from flask import request @blueprint.route('/community') def community_page(): # 获取当前页码,默认显示第1页 page = request.args.get('page', 1, type=int) # 分页查询:每页10条,按发布时间倒序 pagination = Discussions.query.filter(Discussions.title.isnot(None))\ .order_by(Discussions.date.desc())\ .paginate(page=page, per_page=10, error_out=False) discussions_json = [] for discussion in pagination.items: # 优化提示:可通过join关联User表,避免循环中重复查询数据库 user = User.query.filter_by(id=discussion.autor).first() discussions_json.append( { "id": discussion.id, "title": discussion.title, "text": discussion.text, "date": discussion.date, "username": user.username if user else "匿名", "answer_count": discussion.answer_count() } ) # 将分页对象和数据传给模板 return render_template("community.html", discussions_json=discussions_json, pagination=pagination)
2. 修改Jinja模板,添加分页导航
保留原讨论列表循环,在列表下方添加分页控制按钮:
<!-- 原讨论列表渲染逻辑 --> {% 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 %} <!-- 分页导航控件 --> <div style="margin-top: 20px; text-align: center;"> <!-- 上一页按钮 --> {% if pagination.has_prev %} <a href="{{ url_for('blueprint.community_page', page=pagination.prev_num) }}" style="margin: 0 5px; padding: 8px 12px; background: #0abab5; color: white; text-decoration: none;">上一页</a> {% else %} <span style="margin: 0 5px; padding: 8px 12px; background: #ccc; color: #666;">上一页</span> {% endif %} <!-- 页码列表 --> {% for page_num in pagination.iter_pages(left_edge=1, right_edge=1, left_current=2, right_current=3) %} {% if page_num %} {% if page_num == pagination.page %} <span style="margin: 0 5px; padding: 8px 12px; background: #0abab5; color: white; font-weight: bold;">{{ page_num }}</span> {% else %} <a href="{{ url_for('blueprint.community_page', page=page_num) }}" style="margin: 0 5px; padding: 8px 12px; background: #eee; color: #333; text-decoration: none;">{{ page_num }}</a> {% endif %} {% else %} <span style="margin: 0 5px;">...</span> {% endif %} {% endfor %} <!-- 下一页按钮 --> {% if pagination.has_next %} <a href="{{ url_for('blueprint.community_page', page=pagination.next_num) }}" style="margin: 0 5px; padding: 8px 12px; background: #0abab5; color: white; text-decoration: none;">下一页</a> {% else %} <span style="margin: 0 5px; padding: 8px 12px; background: #ccc; color: #666;">下一页</span> {% endif %} </div>
pagination.iter_pages会自动生成合理的页码范围,避免页码过多导致的排版问题,参数可根据需求调整。
二、JS + HTML 前端分页方案(适合小数据量)
如果数据量较小,可一次性加载所有数据到前端,通过JS控制DOM元素的显示/隐藏实现分页,底层逻辑是计算当前页的条目索引范围:
1. 修改HTML结构
给每条讨论添加统一类名,新增分页控制区:
<!-- 讨论列表容器 --> <div id="discussions-container"> {% for discussion in discussions_json %} <div class="discussion-item"> <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 /> </div> {% endfor %} </div> <!-- 分页控制区 --> <div id="pagination-controls" style="margin-top: 20px; text-align: center;"> <button id="prev-btn" style="margin: 0 5px; padding: 8px 12px;">上一页</button> <span id="page-info"></span> <button id="next-btn" style="margin: 0 5px; padding: 8px 12px;">下一页</button> </div>
2. 添加JS分页逻辑
在页面底部插入JS代码:
document.addEventListener('DOMContentLoaded', function() { const itemsPerPage = 10; // 每页显示10条 const items = document.querySelectorAll('.discussion-item'); const totalItems = items.length; const totalPages = Math.ceil(totalItems / itemsPerPage); let currentPage = 1; // 渲染指定页码的内容 function showPage(page) { const startIndex = (page - 1) * itemsPerPage; const endIndex = startIndex + itemsPerPage; // 控制每条讨论的显示状态 items.forEach((item, index) => { item.style.display = index >= startIndex && index < endIndex ? 'block' : 'none'; }); // 更新页码信息 document.getElementById('page-info').textContent = `第 ${page} 页 / 共 ${totalPages} 页`; // 禁用/启用分页按钮 document.getElementById('prev-btn').disabled = page === 1; document.getElementById('next-btn').disabled = page === totalPages; } // 上一页点击事件 document.getElementById('prev-btn').addEventListener('click', () => { if (currentPage > 1) showPage(--currentPage); }); // 下一页点击事件 document.getElementById('next-btn').addEventListener('click', () => { if (currentPage < totalPages) showPage(++currentPage); }); // 初始化显示第一页 showPage(currentPage); });
内容的提问来源于stack exchange,提问作者wicki77
相关产品推荐
相关产品推荐

