当博客有很多文章后,在首页显示所有文章,会让加载速度变慢,同时也会影响浏览体验。一个好的办法,就是对博文进行分页,每页仅显示一部分文章,然后通过导航跳转到相应的页面。如果使用Flask,可以利用SQLAlchemy和Bootstrap插件的分页功能,高效的实现博客分页效果。
0. 创建虚拟文章数据 想要实现博客的分页功能,首先需要我们的博客有足够的数据,在开发阶段,只能通过自动产生数据的手段来满足要求。Python中的ForgeryPy包,可用于产生虚拟信息。
首先安装forgerypy,pip install forgerypy
为博客的文章Post模型,创建类方法,用来产生虚拟数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Post (db.Model) : __tablename__ = 'posts' id = db.Column(db.Integer, primary_key=True ) title = db.Column(db.String) summary = db.Column(db.String) content = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True , default=datetime.utcnow) author_id = db.Column(db.Integer, db.ForeignKey('users.id' )) @staticmethod def generate_fake (count=100 ) : from random import seed, randint import forgery_py seed() for i in range(count): p = Post(title=forgery_py.lorem_ipsum.title(), summary=forgery_py.lorem_ipsum.sentences(randint(1 ,2 )), content=forgery_py.lorem_ipsum.sentences(randint(5 ,8 )), timestamp=forgery_py.date.date(True ), author_id=User.query.filter_by(is_administrator=True ).first().id ) db.session.add(p) db.session.commit()
1. 在页面中获得分页渲染数据 为了支持分页,我们在视图函数中需要获取到,分页类型的数据。可以利用SQLAlchemy提供的paginate()方法,,来显示某页记录。同时可以使用get方法来获取,通过查询字符串方式添加到URL的页码。
1 2 3 4 5 6 def index () : page = request.args.get('page' , 1 , type=int) pagination = Post.query.order_by(Post.timestamp.desc()).paginate(page, per_page=current_app.config['GRITY_POSTS_PER_PAGE' ], error_out=False ) posts = pagination.items return render_template('index.html' , posts=posts, pagination=pagination)
2. 添加分页导航 paginate()方法返回值是一个Pagination类对象,这个对象在SQLAlchemy中定义。其中很多属性可以用于在模板中生成分页链接,因此将其作为参数传入模板。在模板中利用Bootstrap的分页css类就能实现分页导航。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 {% macro pagination_widget(pagination, endpoint) %} <ul class ="pagination" > <li{% if not pagination.has_prev %} class ="disable" {% endif %}> <a href ="{% if pagination.has_prev %}{{ url_for(endpoint, page=pagination.page-1, **kwargs) }}{% else %}#{% endif %}" > «</a > </li > {% for p in pagination.iter_pages() %} {% if p %} {% if p == pagination.page %} <li class ="active" > {% else %} <li > {% endif %} <a href ="{{ url_for(endpoint, page=p, **kwargs) }}" > {{ p }}</a > </li > {% else %} <li class ="disable" > <a href ="#" > …</a > </li > {% endif %} {% endfor %} <li{% if not pagination.has_next %} class ="disable" {% endif %}> <a href ="{% if pagination.has_next %}{{ url_for(endpoint, page=pagination.page+1, **kwargs) }}{% else %}#{% endif %}" > &rquo;</a > </li > </ul > {% endmacro %}
把创建的宏引入页面
1 2 3 4 5 6 ... {% import "_macros.html" as macros %} ... <div class ="pagination" > {{ macros.pagination_widget(pagination,'.index') }} </div >