文档章节

Flask开发轻博客(七):分页

AllenOR灵感
 AllenOR灵感
发布于 2017/09/10 01:24
字数 1628
阅读 0
收藏 0
点赞 0
评论 0

目录

Flask开发轻博客(一):欢迎来到 Flask 的世界

Flask开发轻博客(二):Flask 模板

Flask开发轻博客(三):Flask 的 Web 表单

Flask开发轻博客(四):数据库

Flask开发轻博客(五):用户登录

Flask开发轻博客(六):用户首页和发布博客

Flask开发轻博客(七):分页


分页简介

应用程序看起来比任何时候都要好,但是还是有个问题。我们把所有关注者的 blog 展示在首页上。如果数量超过上千的话会发生些什么?或者上百万?你可以想象得到,处理如此大数据量的列表对象将会及其低效的。

相反,如果我们分组或者分页显示大量的 blog 呢?效率和效果会不会好一些了?

Flask-SQLAlchemy 天生就支持分页。比如如果我们想要得到用户的前三篇文章,我们可以这样做:

pagination = user.posts.paginate(1, PER_PAGE, False).items

paginate 方法能够被任何查询调用。它接受三个参数:

  • 页数,从 1 开始,
  • 每一页的项目数,这里也就是说每一页显示的 blog 数,
  • 错误标志。如果是 True,当请求的范围页超出范围的话,一个 404 错误将会自动地返回到客户端的网页浏览器。如果是 False,返回一个空列表而不是错误。

paginate 返回的值是一个 Pagination 对象。这个对象的 items 成员包含了请求页面项目(本文是指 blog )的列表。在 Pagination 对象中还有其它有帮助的东西,我们将在后面能看到。

现在让我们想想如何在我们的blog首页视图函数中实现分页。我们首先在配置文件中添加一些决定每页显示的 blog 数的配置项(新建文件app/utils.py)

PER_PAGE = 3

在最后的应用程序中我们当然会使用每页显示的 blog 数大于 3,但是测试的时候用小的数量更加方便。

接着,让我们看看不同页的 URLs 是什么样的。我们知道 Flask 路由可以携带参数,因此我们在 URL 后添加一个后缀表示所需的页面

http://127.0.0.1:5000/user/1           <-- page #1 (default)
http://127.0.0.1:5000/user/1/page/1    <-- page #1

这种格式的 URLs 能够轻易地通过在我们的视图函数中附加一个 route 来实现(文件 app/views.py)

from utils import PER_PAGE

@app.route('/user/<int:user_id>', defaults={'page': 1},  methods=["POST", "GET"])
@app.route('/user/<int:user_id>/page/<int:page>', methods=["POST", "GET"])
@login_required
def users(user_id, page):
        form = AboutMeForm()
        user = User.query.filter(User.id == user_id).first()
        if user.id != current_user.id:
                flash("sorry, you can only view your profile!", "error")
                return redirect("/index")

        if not user:
                flash("The user is not exist.")
                redirect("/index")
        blogs = user.posts.paginate(page, PER_PAGE, False).items

        return render_template("user.html",
                                form=form,
                                user=user,
                                blogs=blogs)

我们新的路由需要页面数作为参数,并且声明为一个整型。同样我们也需要在users函数中添加 page 参数,并且我们需要给它一个默认值。

现在我们已经有可用的页面数,我们能够很容易地把它与配置中的PER_PAGE一起传入posts查询。

现在试试输入不同的 URLs,看看分页的效果。但是,需要确保可用的 blog 数要超过三个,这样你就能够看到不止一页了!

页面导航

我们现在需要添加链接允许用户访问下一页以及/或者前一页,幸好这是很容易做的,Flask-SQLAlchemy 为我们做了大部分工作。

我们现在开始在视图函数中做一些小改变。在我们目前的版本中我们按如下方式使用paginate方法

blogs = user.posts.paginate(page, PER_PAGE, False).items

通过上面这样做,我们可以获得返回自 paginatePagination 对象的 items 成员。但是这个对象还有很多其它有用的东西在里面,因此我们还是使用整个对象(文件 app/views.py)

pagination = Post.query.filter_by(
        user_id = current_user.id
        ).order_by(
        db.desc(Post.timestamp) 
        ).paginate(page, PER_PAGE, False)

为了适应这种改变,我们必须修改模板(文件 app/templates/user.html)

{% for blog in pagination.items %}
    <p style="color:#ff6600;">{{ blog.body }}</p>
    <p style="color:#4c4c4c;">{{ blog.timestamp.strftime("%a, %d %b %Y %H:%M:%S") }}</p>
    <hr />
{% endfor %}

这个改变使得模版能够使用完全的 Paginate 对象。我们使用的这个对象的成员有:

  • has_next:如果在目前页后至少还有一页的话,返回 True
  • has_prev:如果在目前页之前至少还有一页的话,返回 True
  • next_num:下一页的页面数
  • prev_num:前一页的页面数

有了这些元素后,我们产生了这些(文件 app/templates/user.html)

{% if pagination %}
    {% for blog in pagination.items %}
    <p style="color:#ff6600;">{{ blog.body }}</p>
    <p style="color:#4c4c4c;">{{ blog.timestamp.strftime("%a, %d %b %Y %H:%M:%S") }}</p>
    <hr />
    {% endfor %}

    {% if pagination.has_prev %} {# 分页的前端展示 #}
    <a href="{{ url_for('users', user_id=current_user.id, page=pagination.prev_num) }}"><< prev</a>
    {% else %}
    << None
    {% endif %} | 
    {% if pagination.has_next %}
    <a href="{{ url_for('users', user_id=current_user.id, page=pagination.next_num) }}">next >></a>
    {% else %}
    None >>
    {% endif %}

{% else %}
    <p style="color:blue;">the guy is so lazy.....</p>
{% endif %}

因此,我们有了两个链接。第一个就是名为 "prev",这个链接使得我们能够访问上一页。第二个就是 "next",它指向下一页。

当我们浏览第一页的时候,我们不希望看到有上一页的链接,因为这时候是不存在前一页。这是很容易被监测的,因为 posts.has_prev 会是 False。我们简单地处理这种情况,当用户浏览首页的时候,上一页会显示出来,但是不会有任何的链接。同样,下一页也是这样的处理方式。

用户信息页

首页上的分页已经完成了。然而,我们在用户信息页上显示了 blog。

改变是跟修改首页一样的。这是我们需要做的列表:

  • 添加一个额外的路由获取页面数的参数
  • 添加一个默认值为 1 的 page 参数到视图函数
  • 用合适的数据库查询与分页代替伪造的 blog
  • 更新模板使用分页对象

下面就是更新后的视图函数(文件 app/views.py)

@app.route('/user/<int:user_id>', defaults={'page': 1},  methods=["POST", "GET"])
@app.route('/user/<int:user_id>/page/<int:page>', methods=["POST", "GET"])
@login_required
def users(user_id, page):
        form = AboutMeForm()
        user = User.query.filter(User.id == user_id).first()
        if user.id != current_user.id:
                flash("sorry, you can only view your profile!", "error")
                return redirect("/index")

        if not user:
                flash("The user is not exist.")
                redirect("/index")
        blogs = user.posts.paginate(page, PER_PAGE, False).items
        pagination = Post.query.filter_by(
                        user_id = current_user.id).order_by(
                        db.desc(Post.timestamp)
                        ).paginate(page, PER_PAGE, False)


        return render_template("user.html",
                                form=form,
                                user=user,
                                blogs=blogs,
                                pagination=pagination)

最终效果图

如果你正确运行上面的程序那么能得到以下的最终效果图。




本文转载自:http://www.jianshu.com/p/5e03cd202728

共有 人打赏支持
AllenOR灵感
粉丝 10
博文 2139
码字总数 82983
作品 0
程序员
《Flask Web开发:基于Python的Web应用开发实战》.PDF

简介 本书不仅适合初级Web开发人员学习阅读,更是Python程序员用来学习高级Web开发技术的优秀参考书。 • 学习Flask应用的基本结构,编写示例应用; • 使用必备的组件,包括模板、数据库、W...

jackmk ⋅ 2017/08/12 ⋅ 0

好书推荐.flask.>

图书封面: 书籍简介: 1. 学习Flask应用的基本结构,编写示例应用; 使用必备的组件,包括模板,数据库,Web表单和电子邮件支持; 使用包和模块构建可伸缩的大型应用; 实现用户认证,角色和个人资...

满满李 ⋅ 2016/06/03 ⋅ 0

Flask 插件系列 - Flask-SQLAlchemy

简介 Web 开发中,一个重要的组成部分便是数据库了。Web 程序中最常用的莫过于关系型数据库了,也称 SQL 数据库。另外,文档数据库(如 mongodb)、键值对数据库(如 redis)近几年也逐渐在 ...

funhacks ⋅ 2017/11/29 ⋅ 0

Flask 插件系列 - Flask-MongoEngine

简介 MongoDB 是一个文档型数据库,是 NoSQL (not only SQL) 的一种,具有灵活、易扩展等诸多优点,受到许多开发者的青睐。MongoEngine 是一个用来操作 MongoDB 的 ORM 框架,如果你不知道什...

funhacks ⋅ 2017/11/29 ⋅ 0

Flask框架 —— 从入门到精通

更新日期 :2016 - 2 - 26 有开源网友提醒,故为了可阅读性更新排版。 Hello World 作者背景 应用程序简介 要求 安装 Flask 在 Flask 中的 “Hello, World” 下一步? 模板 回顾 为什么我们需...

水果糖 ⋅ 2016/02/26 ⋅ 0

flask使用SQLAlchemy操作mysql

注意:看这篇博客需要先看我之前写的一篇博客,在 https://my.oschina.net/zhuangweihong/blog/780913 (flask获取远程服务器的硬件信息) 这篇博客中有提到,获取远程服务器的硬件信息可以入...

鸿弟 ⋅ 2016/11/09 ⋅ 0

Html+JS+PowerShell打造Web版AD管理系统

QQ群里的Evan童鞋分享了一个利用Flask 调用 Powershell API 实现的运维管理系统。可惜现在该分享被删除了。很喜欢,所以也依样画葫芦做了一个。 后来发现豆子同学实现了一个django的,http:...

tliursc ⋅ 01/11 ⋅ 0

在flask-sqlalchemy中使用分页

其实在使用中sqlalchemy和flask-sqlalchemy还是有点区别的的,sqlalchemy中使用query查询,而flask-sqlalchemy中使用basequery查询,他们是子类与父类的关系,flask-sqlalchemy中分页写的很明...

ranvane ⋅ 2014/01/30 ⋅ 0

从零开始搭建论坛(三):Flask框架简单介绍

前面两篇文章中我们已经了解 Web(HTTP)服务器,Web应用程序,Web框架,WSGI这些 Python Web 开发中的概念。我们知道,Web框架通过将不同Web应用程序中的共性部分给抽象出来,提供一系列通用的...

selfboot ⋅ 2016/10/30 ⋅ 0

python-成长之路

一系列python方面有价值的参考/跟python有关的东西 http://www.path8.net/tn/archives/6017 Tools PyCharm – 来自JetBrains的强大的IDE Python Tools for Visual Studio Eclipse + pydev Ap......

_Mr_Computer_ ⋅ 2016/07/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

20.zip压缩 tar打包 打包并压缩

6月25日任务 6.5 zip压缩工具 6.6 tar打包 6.7 打包并压缩 6.5 zip压缩工具: zip支持压缩目录 zip压缩完之后原来的文件不删除 不同的文件内容其实压缩的效果不一样 文件内有很多重复的用xz压...

王鑫linux ⋅ 2分钟前 ⋅ 0

double类型数据保留四位小数的另一种思路

来源:透析公式处理,有时候数据有很长的小数位,有的时候由在四位以内,如果用一般的处理方法,那么不足四位的小树会补充0到第四位,这样子有点画蛇添足的感觉,不太好看。所以要根据小数的...

young_chen ⋅ 8分钟前 ⋅ 0

Python 优化 回溯下降算法

使用sympy构造表达式,实现回溯下降算法 画出函数图像,先使用暴力搜索,找到最小值约为2.5左右 然后选定初始点,开始进行回溯搜索,下降方向为负梯度方向 完整代码 from matplotlib import...

阿豪boy ⋅ 13分钟前 ⋅ 0

Django配置163邮箱出现 authentication failed(535)错误解决方法

最近用Django写某网站,当配置163邮箱设置完成后,出现535错误即:smtplib.SMTPAuthenticationError: (535, b'Error: authentication failed') Django初始配置邮箱设置 EMAIL_HOST = "smtp.1...

陈墨轩_CJX ⋅ 14分钟前 ⋅ 0

用接口模拟可伸缩枚举(34)

1、枚举的可伸缩性最后证明都不是什么好点子 扩展类型的元素是基本类型实例,基本类型的实例却不是扩展类型的元素,很混乱 目前还没有很好的方法来枚举基本类型的所有元素,及其扩展 可伸缩性...

职业搬砖20年 ⋅ 18分钟前 ⋅ 0

Ubuntu18.04 IDEA快捷键无法使用

IDEA默认的回退到上一视图的快捷键是Ctrl + Alt + Left,在ubuntu中这个快捷键被占用了,在16.04中可以在界面中取消这个快捷键,但是18.04就看不到了,可以使用以下命令解决 gsettings set ...

Iceberg_XTY ⋅ 22分钟前 ⋅ 0

如何解决s权限位引发postfix及crontab异常

一、问题现象 业务反馈某台应用服务器,普通用户使用mutt程序发送邮件时,提示“postdrop warning: mail_queue_enter: create file maildrop/713410.6065: Permission denied”,而且普通用法...

问题终结者 ⋅ 34分钟前 ⋅ 0

Unable to load database on disk

由于磁盘空间满了以后,导致zookeeper异常退出,清理磁盘空间后,zk启动报错,信息如下: 2018-06-25 17:18:46,904 INFO org.apache.zookeeper.server.quorum.QuorumPeerConfig: Reading co...

刀锋 ⋅ 54分钟前 ⋅ 0

css3 box-sizing:border-box 实现div一行多列

<!DOCTYPE html><html><head><style> div.container{ background:green; padding:10px 10px;}div.box{box-sizing:border-box;-moz-box-sizing:border-box; /* Fir......

qimh ⋅ 59分钟前 ⋅ 0

Homebrew简介和基本使用

一、Homebrew是什么 Homebrew是一款Mac OS平台下的软件包管理工具,拥有安装、卸载、更新、查看、搜索等很多实用的功能。简单的一条指令,就可以实现包管理,而不用你关心各种依赖和文件路径...

说回答 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部