美文网首页web_front-end
Flask系列:工作流程

Flask系列:工作流程

作者: 超net | 来源:发表于2016-02-11 09:26 被阅读1895次

    这个系列是学习《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 '<h1>Hello World!</h1>'
    

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

    查看URL 映射

    >>> from run import app
    >>> app.url_map
    Map([<Rule '/' (HEAD, POST, OPTIONS, GET) -> index>,
     <Rule '/user/<username>' (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/<name>') # 对 url 中,/user/ 后面的内容进行匹配、截取,赋值给变量 name,默认匹配字符串,可以指定类型。例如,/user/<int:id> 只匹配 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 '<h1>Bad Request</h1>', 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('<h1>This document carries a cookie!</h1>')
             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/<id>')
        def get_user(id):
            user = load_user(id)
            if not user:         # 如果用户不存在
                abort(404)       # 抛出异常
            return '<h1>Hello, %s</h1>' % 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系列:工作流程

        本文链接:https://www.haomeiwen.com/subject/saqukttx.html