Flask系列:工作流程

这个系列是学习《Flask Web开发:基于Python的Web应用开发实战》的部分笔记

客户端——web 服务器——WSGI——application

客户端发送 HTTP 请求,web 服务器在一个地址的端口上等待接收,一旦收到,会将请求通过 WSGI 交给 application 处理,application 就是 flask 框架编写的应用,application 对消息处理后,也通过 WSGI 返回 HTTP 响应给 web 服务器,由服务器发送给客户端。

所有 Flask 程序都必须创建一个程序实例,实例是 Flask 类的对象

安装

$ pip install flask
Collecting flask
Collecting itsdangerous>=0.21 (from flask)
Collecting Werkzeug>=0.7 (from flask)
  Using cached Werkzeug-0.11.2-py2.py3-none-any.whl
Collecting Jinja2>=2.4 (from flask)
  Using cached Jinja2-2.8-py2.py3-none-any.whl
Collecting MarkupSafe (from Jinja2>=2.4->flask)
Installing collected packages: itsdangerous, Werkzeug, MarkupSafe, Jinja2, flask
Successfully installed Jinja2-2.8 MarkupSafe-0.23 Werkzeug-0.11.2 flask-0.10.1 itsdangerous-0.24

创建实例:

run.py

from flask import Flask
app = Flask(__name__)

Flask 函数需要指定一个参数,是程序主模块或包的名字,大多数情况下,__name__就是需要的值。

Flask 用这个参数决定程序的根目录,以便稍后能够找到相对于程序根目录的资源文件。

web 服务器

常见的有 uWSGI、Nginx、gunicorn 等

flask 集成了一个开发用的web服务器,同一时间只能处理一个请求

使用 flask 集成的服务器

run.py

if __name__ == '__main__':
    app.run(debug=True)

debug = True, 调试模式,激活调试器,当一些文件修改保存后,会自动重新加载,而且出错时,能够显示足够的提示信息,具体到运行哪个文件的哪一行产生的错误,错误原因是什么。正因为会提供丰富的后台信息,所以强烈建议不要在生产环境中开启。

运行

$ python run.py
 * Running on http://127.0.0.1:5000/
 * Restarting with reloader

WSGI

web 服务器和 web 框架 有很多种,并不总是能互相配合工作,那就要想办法在它们之间搭建一个沟通的桥梁,让它们能正常互发消息,于是出现了 WSGI 规范,规定了 web 服务器将客户端的消息发送给 application ,以及 application 将处理后的消息发送给服务器的方法,这个规范在PEP 333中定义。

flask 对消息的处理

上下文

在多线程服务器中,定义了一个线程池,由多个线程同时处理不同客户的不同请求(并发),当收到请求后,会选一个线程进行处理。flask 使用 程序/请求 上下文,临时把某些对象在一个线程中设置为“全局可访”,这样既不会干扰其他线程,又使得所有视图都能够访问这些对象,并处理请求。flask 收到请求后,在将请求交给线程之前,会 激活/推送 上下文,建立环境,上下文的内容来自 web 服务器 通过 WSGI 发给 application 的消息,当请求处理完成后,再删除上下文。

在 Flask 中有两种上下文: 程序上下文 和 请求上下文 全局变量

| 变量名 | 上下文说明 |
|---|---|---|
| current_app | 当前激活程序的程序实例 |
| g | 处理请求时用作临时存储的对象。每次请求都会重置这个变量 |
| request | 请求对象,封装了客户端发出的 HTTP 请求中的内容 |
| session | 用户会话,用于存储请求之间需要“记住”的值的词典 |

路由、视图函数

  • URL 映射

创建视图时,会将 URL、HTTP 方法 和特定的视图进行绑定,建立URL 映射

run.py

@app.route('/')  # 使用程序实例提供的`app.route`修饰器,把函数与URL绑定
def index():
    return '

Hello World!

'

用浏览器访问http://localhost:5000/

查看URL 映射

>>> from run import app
>>> app.url_map
Map([ index>,
 ' (HEAD, OPTIONS, GET) -> main.user>])
>>>

GET、POST 是请求方法,由路由进行处理。Flask 为每个路由都指 定了请求方法,这样不同的请求方法发送到相同的 URL 上时,会使用不同的视图函数进 行处理。HEAD 和 OPTIONS 由 Flask 自动处理。

当线程收到 HTTP 请求后,在URL映射中寻找相应 URL、HTTP方法 对应的视图,由该视图进行处理,并返回响应给 web 服务器,发送给客户端。

某些 URL 格式,会发现很多地址中都包含可变部分,Flask 支持这种形式的 URL,只需在 route 修饰器中使用特殊的句法即可

  • 关键字参数
http://localhost:5000/user/john

@app.route('/user/') # 对 url 中,/user/ 后面的内容进行匹配、截取,赋值给变量 name,默认匹配字符串,可以指定类型。例如,/user/ 只匹配 id 为整数的 URL
def user(name): # 变量 name 作为参数传递给函数 user
    print name
  • 额外参数

作为 查询字符串(url 中问号后面的),这个参数可从 request.args 字典中读取

http://127.0.0.1:5000/index?page=2

@app.route('/index')
def index():
    page = request.args.get('page', 1, type=int)

print request.args

ImmutableMultiDict([('page', u'2')])

page=request.args.get('page', 1, type=int) 从 url 获取 键为 page 的 值转换为整形,如果没有 或 转换失败,默认为 1

钩子

在将请求交给视图处理前,或将视图处理的结果返回给 web 服务器前,可以调用钩子,对 请求/响应 进行处理。例如,对于一个用户的请求,检查这个用户的账号有没有通过邮箱确认,如果没有,对某些页面的访问会被禁止访问,重定向到一个特定的页面,而其他页面正常访问。

请求钩子使用修饰器实现。Flask 支持以下 4 种钩子:

  1. before_first_request:注册一个函数,在处理第一个请求之前运行。
  2. before_request:注册一个函数,在每次请求之前运行。
  3. after_request:注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行。
  4. teardown_request:注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行。

响应

Flask 调用视图函数后,会将其返回值作为响应的内容。大多数情况下,响应就是一个简单的字符串,作为 HTML 页面(也就是 HTTP 的 body)回送客户端。

  • 元组

但 HTTP 协议需要的不仅是作为请求响应的字符串。HTTP 响应中一个很重要的部分是状态码,Flask 默认设为 200,这个代码表明请求已经被成功处理。如果视图函数返回的响应需要使用不同的状态码,那么可以把数字代码作为第二个返回值,添加到响应文本之后。

@app.route('/')
def index():
    return '

Bad Request

', 400

视图函数返回的响应还可接受第三个参数,这是一个由首部(header)组成的字典 ,可以 添加到 HTTP 响应中。

  • Response 对象

如果不想返回由 1 个、2 个或 3 个值组成的元组,Flask 视图函数还可以使用 make_response() 产生并直接返回完整的Response 对象。make_response() 函数可以接受 1 个、2 个或 3 个参数(和视图函数的返回值一样),并返回一个Response 对象。有时我们需要在视图函数中产生Response 对象,然后在Response 对象上调用各种方法,进一步 设置响应 。

from flask import make_response
     @app.route('/')
     def index():
         response = make_response('

This document carries a cookie!

') response.set_cookie('answer', '42') # 设置 cookie return response
  • 重定向

有一种名为重定向的特殊响应类型。这种响应没有页面文档, 只是用于告诉浏览器一个新地址,以便加载新页面。重定向经常在 Web 表单中使用。

重定向经常使用 302 状态码表示,指向的地址由 HTTP 的Location 首部提供。重定向响应可以使用 3 个值形式的返回值生成,也可在 Response 对象中设定。不过,由于使用频繁,Flask 提供了redirect() 辅助函数, 用于生成这种响应。

from flask import redirect

@app.route('/')
def index():
    return redirect('http://www.example.com')
  • 异常跳出

还有一种特殊的响应由abort 函数生成,用于处理错误。

from flask import abort

@app.route('/user/')
    def get_user(id):
        user = load_user(id)
        if not user:         # 如果用户不存在
            abort(404)       # 抛出异常
        return '

Hello, %s

' % user.name

注意,abort 会直接跳出调用它的函数,抛出异常,把控制权交给 Web 服务器。

flask 的组件

被设计为可扩展形式,只自带两个核心组件:

  • werkzeug,负责处理 路由、调试、WSGI
  • jinja2,模板引擎,负责对模板进行渲染

其他组件需要单独安装、初始化

扩展的来源:

  • 社区开发
  • py 标准库/包
  • 自行开发

使用:

pip install flask-mail # pip 安装

from flask.ext.mail import Mail # 导入, 专为 Flask 开发的扩展,都在 flask.ext 命名空间下, virtualenv 环境中,目录为lib/python2.7/site-packages/

mail = Mail(app) # 初始化,将 程序实例(app) 作为参数传给 扩展的构造函数,进行初始化。通常在创建程序实例时进行。

mail.send(msg) # 使用

你可能感兴趣的:(Flask系列:工作流程)