今天我们正是开始 Flask 的学习之旅,Flask 作为一个轻量级的 Python Web 开发框架,以其良好的扩展性和易用性,俘获了大量的簇拥者,下面就让我们一起走进 Flask 的世界吧。
准备工作
语言储备
在学习 Flask 之前,你应该对 Python 和 HTML 的基础语法有了一定的了解,如果还使用过 JavaScript 语言那就更棒了。
对于 Python 语言就不用说了,Flask 就是 Python 的 Web 框架,如果没有 Python 语言基础,又怎么能够书写 Flask 代码呢。
而对于 HTML 基础,甚至是 JavaScript 基础来说,都是 Web 的基础知识,因为我们在编写 Web 程序的时候,不仅仅需要编写后台逻辑,对于前端代码也会涉及到,比较构建前端页面,通过 AJAX 提交数据等等。这些都是需要 HTML 和 JavaScript 语言基础的支撑的。
环境准备
首先你当然需要拥有一个 Python 开发环境,无论是 Windows,MacOS 还是 Linux 系统,安装 Python 都是很简单的事情,不过对于没有 Unix 操作系统使用经验的初学者来说,我还是比较建议使用 Windows 作为开发环境。
而编辑器我推荐使用 PyCharm,它集成了丰富的插件,可以极大的提高我们的开发效率,当然诸如 Sublime 等轻量级的编辑器也是很不错的,这个就看个人的喜好情况了。
当然,既然要学习 Web 开发,浏览器也一定是必备的,你的电脑上一定按照了 Chrome 或者 FireFox 吧,足够了!
接下来就是安装 Flask,使用 pip 安装即可,非常方便
pip install flask
现在我们已经完成了前期的准备工作,下面就一起来认识下 Flask 吧。
Hello Flask
追溯到最初,Flask 诞生于 Armin Ronacher 在 2010 年愚人节开的一个玩笑。后来,它逐渐发展成为一个成熟的 Python Web 框架,越来越受到开发者的喜爱。目前它在 GitHub 上是 Star 数量最多的 Python Web 框架,甚至都超过了大名鼎鼎的 Django。
Flask 是典型的微框架,作为 Web 框架来说,它仅保留了核心功能:请求响应处理和模板渲染。这两类功能分别由 Werkzeug(WSGI 工具库)完成和 Jinja(模板渲染库)完成。至于我们如果要实现其他的功能,比如收发邮件,处理 WebSocket 请求,快速构建前端页面等,则可以使用 Flask 强大而丰富的扩展插件,这些我们在后面的学习中再慢慢介绍。
一个最小程序
创建目录
首先我们先完成一个最小的 Web 程序,在浏览器页面上打印出 Hello Flask 字符。
我们现在自己的本地目录中创建一个项目文件夹,可以命名为“HelloFlask”。
然后使用 PyCharm 打开该目录文件夹
现在,PyCharm 会是下图的样子
接下来我们右击 HelloFlask 文件夹,在弹出的菜单中选择 New->Python file,命名为“app”。
这个时候我们双击打开 app.py 文件,可能会看到“No Python interpreter”的提示,我们可以点击“Configure”的按钮,进行配置
在弹出的对话框中选择你安装的 Python 的目录
之后点击“OK”按钮即可。
编写最小程序代码
下面我们先给出这段代码,并演示下效果
from flask import Flaskapp = Flask(__name__)@app.route('/')
def hello():
return 'Hello Flask!'
if __name__ == '__main__':
app.run(debug=True)
下面我们点击 if 代码旁边的绿色箭头,选择“Run app”,如果不出意外,PyCharm 会弹出控制台,并打印程序启动相关信息
现在打开浏览器,输入“http://127.0.0.1:5000/”,就可以访问我们程序的首页了
可以看到,通过 Flask 来创建 Web 应用实在是太简单了,最小的 Web 程序总代码还不到10行,而这正是 Flask 最大的优势。
解析时间
下面我们就来分解这个程序,来看看它的构成是怎样的
初始化程序实例
首先我们从 flask 包导入 Flask 类,通过实例化这个类,创建一个程序对象 app:
from flask import Flaskapp = Flask(__name__)
传入 Flask 类构造方法的第一个参数就是模块或包的名称,一般情况下,我们可以使用特殊变量__name__ 来代指。
Flask 通过这个参数来决定程序的根目录,以便后面找到相对于程序根目录的静态资源文件的位置。
路由和视图函数
客户端(例如 Web 浏览器)把请求发送给 Web 服务器,Web 服务器再把请求发送给 Flask 程序实例。程序实例需要知道对每个 URL 请求运行哪些代码,所以保存了一个 URL 到 Python 函数的映射关系。处理 URL 和函数之间关系的程序称为路由。
而视图函数就是处理某个请求的函数,即我们程序的后台逻辑处理函数。
在 Flask 中,定义一个路由时非常方便的,直接使用 app.route() 装饰器来为这个函数绑定对应的 URL 即可。当用户在浏览器访问这个 URL 的时候,就会触发这个函数,获取返回值,并把返回值显示到浏览器窗口:
@app.route('/')
def hello():
return 'Hello Flask!'
app.route() 装饰器的第一个参数是 URL 规则字符串,这里的 / 指的是根地址。把根地址和 hello 函数绑定起来,当用户访问这个 URL 时就会触发 hello 函数。而这个函数可以像其他任何普通函数一样执行任意操作,比如操作数据库,对用户提交的数据进行计算等等。
视图函数返回的响应可以时包含 HTML 的简单字符,也可以是复杂的表单等等。
而对于 URL 规则字符串,如果我们写成 /hello 这种形式,那么我们就需要通过访问http://127.0.0.1:5000/hello 来进入 hello 这个函数。即 app.route() 这个装饰器,必须以斜杠 / 开头,且是不包含域名的 URL(在例子中,域名为http://127.0.0.1:5000)。
下面我们整理下总的请求过程
- 用户在浏览器地址栏访问这个地址,在这里即http://127.0.0.1:5000
- 服务器解析请求,发现请求 URL 匹配的 URL 规则是 /,因此调用对应的处理函数 hello()
- 获取 hello() 函数的返回值,处理后返回给客户端(浏览器)
- 浏览器接受响应,将其显示在窗口上
启动服务器
在例子中,是使用 run 方法来启动 Web 服务器的
if __name__ == '__main__':
app.run(debug=True)
name == ‘main’ 在 Python 当时是非常常见的用法,可以简单理解为直接执行该文件,才会启动 Web 服务器。而传递给 run 方法的 debug 参数,则决定了是否启用 debug 模式,在开发阶段,打开 debug 模式可以方便我们定位分析问题。同时在 debug 模型下,我们修改了某些代码,在保存之后无需重启 Web 服务器,可以直接重新装在应用程序,体现代码的修改结果,非常方便。
Flask 内置了一个简单的开发服务器(由依赖包 Werkzeug 提供), 足够在开发和测试阶段使用。但是对于生成环境,则需要使用性能足够好的生成服务器,以此来提高安全和性能。
当然,上面实例中的 app.run() 是老的启动服务器的方法,这非常方便我们在 PyCharm 中进行调测,而在最新的 Flask 版本中,更加推荐使用命令行的方式来启动 Flask Web 服务器,即当我们安装好 Flask 后,会自动添加一个 flask 命令脚本,可以通过下面的命令启动服务器
$ flask run
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
对于 flask run 这种启动方式,我们会在后面部署生成环境时再着重介绍,后面对于开发环境,我们都会使用 app.run() 的方式来启动。
增强服务器
多 URL 绑定
一个视图函数,是可以绑定多个 URL 地址的,比如我们可以把 /hello 和 /say 都绑定到 hello 函数上,那么当用户访问这两个 URL 时都会触发 hello 函数,并得到相同的响应结果。
@app.route('/hello')
@app.route('/say')
def hello():
return 'Hello Flask!'
而此时由于我们删除了 / 的路由,所以再访问根地址时就会报错
动态 URL
在我们日常访问的 Web 服务器中,有很多访问地址是如下形式的
http://xxx.xxx/abc/<your-name>
其中的 是根据不同人来变化的,这种就属于动态 URL 地址,Flask 可以很好的支持这种形式。
@app.route('/user/<name>')
def welcome(name):
return '<h1>Hello, %s!</h1>' % name
视图函数可以接收 URL 传递过来的参数,并生成对应于不同人的欢迎语!
同时我们还注意到,上面 welcome 函数的返回值里包含了 HTML 代码
,这就是我们上面提到的,视图函数可以返回 HTML 字符。
动态 URL 增强
如果我们只输入地址 /user,而不携带任何字符的话,我们的 Web 程序就会报 404 的错误,很正常,因为没有匹配到任何 URL 规则嘛,那么对于一个陌生人我们该如何处理呢,答案就是增加一个默认值!
@app.route('/user/', defaults={'name': '陌生人'})
@app.route('/user/<name>')
def welcome(name):
return '<h1>Hello, %s!</h1>' % name
URL 与端点
在 Web 程序中,URL 实在是太重要了,可以说无处不在。如果我们把所有的 URL 地址都以硬编码的方式写出,那么在后期的维护上会付出很大的代价。
同时,对于上面例子中的动态 URL,我们没有办法通过硬编码的形式引用该 URL 地址。
那么此时,url_for() 这个神奇的函数就登场了,它可以完美的通过视图函数名称来产生对应的 URL 地址。
调用 url_for 时,第一个参数为端点(endpoint)值。在 Flask 中,端点用来标记一个视图函数以及对应的 URL 规则,其默认值为视图函数的名称。
端点的理解
我们可以在当前项目的目录下启用 cmd,并输入 flask routes 来查看当前的路由信息
C:\Work\personal document\Flask Web\code\HelloFlask>flask routes
Endpoint Methods Rule
-------- ------- -----------------------
hello GET /hello
hello GET /say
static GET /static/<path:filename>
welcome GET /user/<name>
welcome GET /user/
可以看到,端点的默认值即为视图函数的名称。
当然我们还可以在注册路由时通过 endpoint 参数来修改端点值
@app.route('/hello')
@app.route('/say', endpoint='new')
def hello():
return 'Hello Flask!'
再次查看程序的路由信息
C:\Work\personal document\Flask Web\code\HelloFlask>flask routes
Endpoint Methods Rule
-------- ------- -----------------------
hello GET /hello
new GET /say
static GET /static/<path:filename>
welcome GET /user/<name>
welcome GET /user/
路由 /say 对应的端点已经改变了。
那么到底为什么要引入端点这个概念呢,其实这是和 Flask 蓝图息息相关的,这部分我们放到后面讲解蓝图部分再详细说明。
url_for 函数
现在我们回到 url_for 函数,我们知道调用 url_for 函数时,第一个参数就是端点,而它返回的就是端点所对应的路由地址,我们修改代码,来实验下
from flask import Flask, url_for
@app.route('/user/', defaults={'name': '陌生人'})
@app.route('/user/<name>')
def welcome(name):
print(url_for('hello'))
return '<h1>Hello, %s!</h1>' % name
这里注意我们需要先导入 url_for 函数
当我们在浏览器访问 /user 这个 URL 地址时,就会触发 welcome 函数,就会在控制台打印一行信息,即为 url_for 的返回结果
可以看到打印出的信息为“/hello”,确实为 hello 视图函数对应的 URL 地址。同时我们也发现,当我们为同一个视图函数注册多个路由时,url_for 函数只会返回最上面的 URL,这一点也值得我们注意。
本教程的代码,可以到 Github 上下载
本小结的代码,可以检出 tag 为 1a 的代码版本
总结
本节我们初步认识了 Flask,并完成了一个最为基本的 Web 程序。同时还学习了多 URL,动态 URL 的配置方法,以及 url_for 函数和端点的相关知识点。