内容简介:Flask 是一个 Python 实现的 Web 开发微框架, 有丰富的生态资源。本文从一段官方的示例代码通过一步步打断点方式解释 Flask 内部的运行机制,在一些关键概念会有相关解释,这些前提概念对整体理解 Flask框架十分重要,本文基于flask 0.1 版本进行相应的分析。第一行import Flask 类对象,这个无需解释。跳到第二行,使用当前模块的名字传入Flask类中,并实例化Flask对象,我们在这个地方打个断点,看看Flask类别里有什么。上图可以看出,Flask类中定义jinia_o
Flask 是一个 Python 实现的 Web 开发微框架, 有丰富的生态资源。本文从一段官方的示例代码通过一步步打断点方式解释 Flask 内部的运行机制,在一些关键概念会有相关解释,这些前提概念对整体理解 Flask框架十分重要,本文基于flask 0.1 版本进行相应的分析。
官方demo示例
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run() 复制代码
第一行import Flask 类对象,这个无需解释。跳到第二行,使用当前模块的名字传入Flask类中,并实例化Flask对象,我们在这个地方打个断点,看看Flask类别里有什么。
上图可以看出,Flask类中定义jinia_options、request_class、response_class等属性,这里我们不关系具体作用,先看看源码中Flask 是不是定义了这些属性。
class Flask(object): # 省略了注释部分 # flask 用作请求对象的类 request_class = Request # flask 用作响应对象的类 response_class = Response # 静态文件路径 static_path = '/static' # 密钥,用于加密 session 或其它涉及安全的东西 secret_key = None #存储session对象数据的cookie名称 session_cookie_name = 'session' # Jinja2环境的一些选项 jinja_options = dict( autoescape=True, extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'] ) 复制代码
这部分是初始化Flask类中默认设置的一些属性,其实通过名字也可以大概知道每个属性的作用。看到这个地方时是不是一脸懵逼,Request、Response 是什么东西,有什么作用?Jinja2 又是什么东西? 别急,下面慢慢解释这几个东西的作用。
Request && Response
from werkzeug import Request as RequestBase, Response as ResponseBase class Request(RequestBase): """The request object used by default in flask. Remembers the matched endpoint and view arguments. It is what ends up as :class:`~flask.request`. If you want to replace the request object used you can subclass this and set :attr:`~flask.Flask.request_class` to your subclass. """ def __init__(self, environ): RequestBase.__init__(self, environ) self.endpoint = None # 请求对象的端点 self.view_args = None # 请求视图函数的参数 class Response(ResponseBase): """The response object that is used by default in flask. Works like the response object from Werkzeug but is set to have a HTML mimetype by default. Quite often you don't have to create this object yourself because :meth:`~flask.Flask.make_response` will take care of that for you. If you want to replace the response object used you can subclass this and set :attr:`~flask.Flask.request_class` to your subclass. """ default_mimetype = 'text/html' 复制代码
通过源码的注释我们可以知道,Request、Response都只是对 werkzeug 库的Request、Response 进行了一层包装并加入一些属性。先说一下它们的作用:
- Request 的作用:是 flask 默认的请求对象,用来记住匹配的endpoint(端点)和view arguments(视图参数)
- Response 的作用:是 flask 默认的响应对象,默认设置MIME类型默认设置为HTML(即是定义了内容类型 Content-Type 返回的类型为HTML), 默认情况下,你不用自己创建这个对象,因为下面的 make_response 函数会帮你处理。
看完上面源码和解释,是不是有新的疑问了,werkzeug又是什么?端点又是什么概念?额,werkzeug的作用真的很大,整个框架都是基于它实现的,下面会有一个部分专门说明这个库。说明: werkzeug 库和 jinja2 是 flask 的两个依赖库,会分出一篇文章专门介绍,这篇文章重点是整个 Flask 内部的机制,建议看到对应部分,先提前去读两个依赖库的文章。
接下来继续下一步的调试,初始化一个Flask类, 先看看 Flask 类的初始化函数:
def _get_package_path(name): """Returns the path to a package or cwd if that cannot be found.""" # 获取 模块包 路径,被 Flask 引用 try: return os.path.abspath(os.path.dirname(sys.modules[name].__file__)) except (KeyError, AttributeError): return os.getcwd() class Flask(object): # 简化版,已经去掉注释,建议看源码注释加上这个理解 def __init__(self, package_name): # 设置是否开启调试模式,若开启,会监视项目代码变化, # 开发服务器重载 Flask 应用 self.debug = False # 包或模块的名字,模块的名称将会因其作为单独应用启动还是作为模块导入而不同 # Flask 才知道到哪去找模板、静态文件 self.package_name = package_name # 根据 Flask 传入的__name__, 找到项目的根路径 self.root_path = _get_package_path(self.package_name) # 已注册的所有视图函数的字典,字典的键是函数名称,可以用来生成URL(url_for函数) # 字典的值是函数本身, 想要注册视图函数,可以使用 route 装饰器 self.view_functions = {} # 所有已注册错误处理程序的字典, 字典的键是一个整数类型(integer)的错误码 # 字典的值是对应错误的函数,想要注册错误handler, 可以使用 errorhandler 装饰器 self.error_handlers = {} # 请求开始进入时,但还请求还没调度前调用的函数列表,也就是预处理操作 # 可用于打开数据库连接或获取当前登录用户,使用 before_route 装饰器注册 self.before_request_funcs = [] # 请求结束时调用的函数列表,这些函数会被传入当前响应对象并将其修改或替换它。 self.after_request_funcs = [] # 不带参数调用的函数列表,用于填充模板上下文,每个应该返回更新模板上下文的字典 # 默认的处理器用来注入session、request和g self.template_context_processors = [_default_template_ctx_processor] # 使用 werkzeug 的 routing.Map, 用于给应用增加一些URL规则, # URL规则形成一个Map实例的过程中会生成对应的正则表达式,可以进行URL匹配 self.url_map = Map() # 添加静态文件的URL映射规则 # SharedDataMiddleware中间件用来为程序添加处理静态文件的能力 if self.static_path is not None: self.url_map.add(Rule(self.static_path + '/<filename>', build_only=True, endpoint='static')) if pkg_resources is not None: target = (self.package_name, 'static') else: target = os.path.join(self.root_path, 'static') self.wsgi_app = SharedDataMiddleware(self.wsgi_app, { self.static_path: target # URL路径和实际文件目录(static文件夹)的映射 }) # Jinja2 环境,它通过jinja_options创建,加载器(loader)通过 self.jinja_env = Environment(loader=self.create_jinja_loader(), **self.jinja_options) # 将url_for, get_flashed_message 作为全局对象填充入模板上下文中,可以在模板中调用它们 self.jinja_env.globals.update( url_for=url_for, get_flashed_messages=get_flashed_messages ) 复制代码
上面就是一个 Flask 实例化时所做的工作,其实就是保存了一下配置信息,设置了一下Jinja2 环境,并定义了一个URL 映射对象,用于映射URL 到函数之间的关系。
以上所述就是小编给大家介绍的《Flask 源码阅读笔记 开篇》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Netty 核心源码解读(开篇)
- dubbo源码解析(三十四)集群——开篇
- Hyperledger-Fabric源码分析(开篇)
- http性能测试工具wrk源码学习之开篇
- DuckDB:开篇
- Android插件化开篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ruby元编程(第2版)
[意] Paolo Perrotta / 廖志刚 / 华中科技大学出版社 / 2015-8-1 / 68.80
《Ruby元编程(第2版)》在大量剖析实例代码的基础上循序渐进地介绍Ruby特有的实用编程技巧。通过分析案例、讲解例题、回顾Ruby类库的实现细节,作者不仅向读者展示了元编程的优势及其解决问题的方式,更详细列出33种发挥其优势的编程技巧。本书堪称动态语言设计模式。Ruby之父松本行弘作序推荐。一起来看看 《Ruby元编程(第2版)》 这本书的介绍吧!