Python 进阶 (五十) 浅析 Flask 运行原理
一、前言
在学习 Python Web 开发过程中,掌握了 Flask 的开发方法。经过一段时间的视频学习,回过头来对 Flask 的运行原理做一简要解析,以增强自己对 Flask 的了解。
二、 WSGI
所有的 Python Web 框架都要遵循 WSGI
协议,在这里还是要简单回顾一下 WSGI 的核心概念。
WSGI
中有一个非常重要的概念:每个 Python Web 应用都是一个可调用(callable)的对象。在 flask 中,这个对象就是 app = Flask(__name__)
创建出来的 app,就是下图中的绿色Application
部分。要运行 web 应用,必须有 web server,比如我们熟悉的apache
、nginx
,或者python
中的gunicorn
,我们下面要讲到的 werkzeug 提供的WSGIServer
,它们是下图的黄色 Server 部分。
Server 和 Application 之间怎么通信,就是 WSGI 的功能。它规定了 app(environ, start_response) 的接口,server 会调用 application,并传给它两个参数:environ
包含了请求的所有信息,start_response
是 application 处理完之后需要调用的函数,参数是状态码、响应头部还有错误信息。
WSGI application
非常重要的特点是:它是可以嵌套的。换句话说,可以写个 application,它做的事情就是调用另外一个 application,然后再返回(类似一个 proxy)。一般来说,嵌套的最后一层是业务应用,中间就是 middleware。这样的好处是,可以解耦业务逻辑和其他功能,比如限流、认证、序列化等都实现成不同的中间层,不同的中间层和业务逻辑是不相关的,可以独立维护;而且用户也可以动态地组合不同的中间层来满足不同的需求。
Flask 基于Werkzeug WSGI
工具箱和 Jinja2 模板引擎。 Flask 使用BSD
授权。 Flask 也被称为“microframework”,因为它使用简单的核心,用 extension 增加其他功能。Flask 没有默认使用的数据库、窗体验证工具。然而,Flask 保留了扩增的弹性,可以用 Flask-extension 加入这些功能:ORM、窗体验证工具、文件上传、各种开放式身份验证技术。我们可以这么理解,Flask 是一个核心,而其他功能则是一些插件,需要什么功能,只要找到对应的插件,将其插入核心就能够实现该功能了。
Flask 是怎么将代码转换为我们可见的 Web 网页的。首先,我们得先从 Web 程序的一般流程来看,对于我们的 Web 应用来说,当客户端想要获取动态资源 时,(比如 ASP 和 PHP 这类语言写的网站),这个时候就会发起一个 HTTP 请求(比如用浏览器访问一个 URL),此时 Web 应用程序就会在服务器后台进行相应的业务处理(比如对数据库进行操作或是进行一些计算操作等),取出用户需要的数据,生成相应的 HTTP 响应(当然,如果访问的是 静态资源 ,服务器则会直接返回用户所需的资源,不会进行业务处理)。整个处理工程如下所示:
在实际的应用中,不同的请求可能会调用相同的处理逻辑。这里有着相同业务处理逻辑的 HTTP 请求可以用一类 URL 来标识。比如在我们的博客站点中,对于所有想要获取 Articles 内容的请求而言,可以用 articles/这类 URL 来表示,这里的 article_id 用以区分不同的 article。接着在后台定义一个 get_article(article_id)的函数,用来获取 article 相应的数据,此外还需要建立 URL 和函数之间的一一对应关系。这就是 Web 开发中所谓的路由分发 ,如下图所示:
在 Flask 中,使用 werkzeug 来做路由分发,werkzeug
是Flask
使用的底层WSGI
库(WSGI,全称 Web Server Gateway interface
,或者 Python Web Server Gateway Interface
,是为 Python 语言定义的 Web 服务器和 Web 应用程序之间的一种简单而通用的接口)。
WSGI 将 Web 服务分成两个部分:服务器和应用程序。WGSI 服务器只负责与网络相关的两件事:接收浏览器的 HTTP 请求、向浏览器发送 HTTP 应答;而对 HTTP 请求的具体处理逻辑,则通过调用 WSGI 应用程序进行。WSGI 工作流程如下图所示:
在 Flask 中,路由分发的代码写起来十分简单,如下:
通过业务逻辑函数获得我们所需的数据后,服务器将会根据这些数据来生成 HTTP 响应(对于 Web 应用来说,一般就是一个 HTML 文件,这个是可以直接被我们的客户端,即浏览器直接读取并解释的)。在 Web 开发中,常规的做法是将获取的数据传入 Web 应用提供的一个 HTML 模板文件中,经过模板系统的渲染后最终得到我们所需要的 HTML 响应文件。
一般情况下,虽然请求不同,但是响应中的数据的展示方式是相同的 ,通俗点说就是除了我们请求获得的数据不一样外,其他都是一样的,那么我们就可以设计一个模板(除了数据内容可以改动,其他都是固定的 HTML 文件)。我们以博客站点为例,对不同 article 而言,其具体 article content 虽然不同,但页面展示的内容除了请求的数据外都是一样的,都有标题拦,内容栏等。也就是说,对于 article 来说,我们只需提供一个 HTML 模板,然后传入不同 article 数据,即可得到不同的 HTTP 响应。这就是所谓的模板渲染 ,如下图所示:
在 Flask 中使用 Jinja2 模板渲染引擎来做模板渲染(Jinja2 是基于 python 的模板引擎,功能比较类似于于 PHP 的 smarty,J2ee 的 Freemarker 和 velocity。它能完全支持 unicode,并具有集成的沙箱执行环境,应用广泛。jinja2 使用 BSD 授权)。Jinja2 的工作流程如下图所示:
在 Flask 中,模板渲染的代码写起来也是十分的便捷,代码如下:
在Flask
中,我们处理一个请求的流程就是,首先根据用户提交的 URL 来决定由哪个业务逻辑函数来处理,然后在函数中进行操作,取得所需的数据。再将取得的数据传给相应的模板文件中,由 Jinja2 负责渲染得到 HTTP 响应内容,即 HTTP 响应的 HTML 文件,然后由 Flask 返回响应内容。
三、实例项目
下面主要以实例项目对 Flask 运行原理做一简要解析。在实例项目中,使用到了程序工厂函数和蓝本。项目目录结构如下:
在 manager.py 文件中,定义了项目启动的入口函数:
同时,在该文件中创建了工厂方法实例:
在工程方法中,对数据库进行了相关配置,创建了前端导航栏,同时对所创建的蓝本进行了注册。在创建的蓝本中主要涉及授权、路由及错误处理模块。
版权声明: 本文为 InfoQ 作者【No Silver Bullet】的原创文章。
原文链接:【http://xie.infoq.cn/article/ddebf01edf8f0ecd3d8c4399b】。文章转载请联系作者。
评论