flask基础之app初始化(四)

前言

flask的核心对象是Flask,它定义了flask框架对于http请求的整个处理逻辑。随着服务器被启动,app被创建并初始化,那么具体的过程是这样的呢?

系列文章

一个最基本web应用的flask代码

from flask import Flask
import os

# 创建app对象
app = Flask(__name__,template_folder=‘static/html‘)
# 加载配置文件
app.config[‘SECRET_KEY‘] = ‘123‘
# 加载蓝图
app.register_blueprint(rest, url_prefix=‘‘)

# 加载请求钩子
@rest.before_request
def rest_test():
    print(‘this is a test‘)
    pass

# 定义api处理视图
@app.route(‘/test1‘)
def test():
    return ‘OK‘

@定义错误处理逻辑
@app.errorhandler(400)
def handle_errer(errer):
    print(errer)
    return errer

if __name__ == ‘__main__‘:
    app.run(host=‘127.0.0.1‘, port=80, debug=True)

如上所示,一个完整的web应用所拥有的最基本的东西就这些了,我们一步步分析。

第一步:创建Flask对象

创建一个Flask的app对象作为备用是一切的开端,看一下初始化干了什么?

class Flask(_PackageBoundObject):
    request_class = Request # 指定请求对象
    response_class = Response # 指定响应对象
    jinja_environment = Environment # 指定前端模板语言环境
    app_ctx_globals_class = _AppCtxGlobals # 设置app全局对象,本质是一个字典
    request_globals_class = property(_get_request_globals_class, # 设置请求上下文全局对象,其等于app_ctx_globals_class
                                        _set_request_globals_class)
    config_class = Config # 设置参数配置对象
    debug = ConfigAttribute(‘DEBUG‘) # 配置文件中如果DEBUG=True就启用debug模式
    testing = ConfigAttribute(‘TESTING‘) # 配置文件中如果TESTING=True就启用TESTING模式
    secret_key = ConfigAttribute(‘SECRET_KEY‘) # 配置文件中如果SECRET_KEY=‘xx’就启用了密匙,默认是不启用的
    # 配置文件中如果SESSION_COOKIE_NAME=‘xx’就启用了在cookie中session信息的名字,默认是session
    session_cookie_name = ConfigAttribute(‘SESSION_COOKIE_NAME‘)

    # 配置文件中如果PERMANENT_SESSION_LIFETIM=‘xx’就启用了session信息的失效时间,默认是31天,即一个月
    permanent_session_lifetime = ConfigAttribute(‘PERMANENT_SESSION_LIFETIME‘,
                                                    get_converter=_make_timedelta)

    # 设置发送文件功能最大的缓存超时时间,默认为12小时
    send_file_max_age_default = ConfigAttribute(‘SEND_FILE_MAX_AGE_DEFAULT‘,
                                                get_converter=_make_timedelta)

    # 通过LOGGER_NAME指定日志对象的名称
    logger_name = ConfigAttribute(‘LOGGER_NAME‘)

    # 启用json格式的编解码
    json_encoder = json.JSONEncoder
    json_decoder = json.JSONDecoder

    # 设置默认jinja模板环境
    jinja_options = ImmutableDict(
        extensions=[‘jinja2.ext.autoescape‘, ‘jinja2.ext.with_‘]
    )

    # 常用默认的配置集合
    default_config = ImmutableDict({
        ‘DEBUG‘: get_debug_flag(default=False), # 默认不开启DEBUG模式
        ‘TESTING‘: False, # 默认不开启TESTING模式
        ‘SECRET_KEY‘: None, # 默认没有密匙
        ‘PERMANENT_SESSION_LIFETIME‘: timedelta(days=31), # 默认session失效时间一个月
        ‘USE_X_SENDFILE‘: False, # 不启用X_SENDFILE功能
        ‘LOGGER_NAME‘: None, # 不指定logger名字,使用的是__name__
        ‘LOGGER_HANDLER_POLICY‘: ‘always‘,
        ‘SERVER_NAME‘: None, # 设置服务器的名字,默认None
        ‘SESSION_COOKIE_NAME‘: ‘session‘, # 设置cookie中的session名字
        ‘MAX_CONTENT_LENGTH‘: None, # 限制提交请求的最大字节数
        ‘SEND_FILE_MAX_AGE_DEFAULT‘: timedelta(hours=12), # 设置文件最大缓存时间
        ‘PREFERRED_URL_SCHEME‘: ‘http‘, # 默认的通讯协议
        ‘JSONIFY_MIMETYPE‘: ‘application/json‘, # 当json数据交互时,设置响应头的mimetype参数
    })

    url_rule_class = Rule # 指定路由对象管理路由
    session_interface = SecureCookieSessionInterface() # 指定session会话对象
    def __init__(self,
                    import_name, # 指定app的名字
                    static_path=None,  # 会赋值给static_url_path参数,所以一般设置static_url_path而不是这个
                    static_url_path=None, # 设置静态文件路由的前缀,默认为“/static”,即static_folder的路径
                    static_folder=‘static‘, # 指定静态文件是哪个目录
                    template_folder=‘templates‘,# 模板文件的存放目录,默认值为"templates"
                    instance_path=None, # 设置配置文件的路径,在instance_relative_config=True情况下生效
                    instance_relative_config=False, # 设置为True表示配置文件相对于实例路径而不是根路径
                    root_path=None): # app所在的根路径,默认指的是创建app这个代码的文件的目录。

        # 所有定义的视图函数存放字典,以视图函数的标识符为键,视图函数对象为字典;
        self.view_functions = {}

        # 所有自定义的错误处理方法的存放字典,以蓝图名字为键
        self.error_handler_spec = {None: self._error_handlers}

        # 所有的与url错误处理方法存放列表
        self.url_build_error_handlers = []

        # 所有的http请求处理前的请求钩子方法存放字典
        self.before_request_funcs = {}

        # 第一次请求处理前的请求钩子方法存放字典
        self.before_first_request_funcs = []

        # 所有的http请求处理后的请求钩子方法存放字典
        self.after_request_funcs = {}

        # 在处理即使存在异常的情况下的请求处理后的请求钩子方法存放字典
        self.teardown_request_funcs = {}

        # 应用上下文被弹出之前的处理函数存放点
        self.teardown_appcontext_funcs = []

        # url_value_preprocessor装饰器添加,URL路径预提取
        self.url_value_preprocessors = {} 

        # url_defaults装饰器回调添加的,在生成url时设置规则参数默认值
        self.url_default_functions = {} 

        self.blueprints = {} # 所有的蓝图的保存字典

        self.extensions = {} # 所有的flask的扩展对象的存放字典

        self.url_map = Map() # 所有的Rule对象保存的字典

        # 添加访问静态文件的Rule对象
        if self.has_static_folder:
            self.add_url_rule(self.static_url_path + ‘/<path:filename>‘,
                                endpoint=‘static‘,
                                view_func=self.send_static_file)

初始化传入相关的参数后,会执行上述代码生成一个app对象。

第二步:加载配置文件

加载配置文件有多种方式,现在只说例子中的情况:

app.config[‘SECRET_KEY‘] = ‘123‘

app的config对象其实是Config实例,是一个dict类型的子类,也就是说app的配置是通过一个字典来保存的,新加载的配置如果键和原来默认的配置的键相同将更新,否则添加。

class Config(dict):
    pass

详细的参数配置方式参考: flask之安装和使用入门

第三步:加载蓝图

app的register_blueprint方法就是用来加载蓝图的。

app.register_blueprint(rest, url_prefix=‘‘)

# 源码
def register_blueprint(self, blueprint, **options):
        ......
        self.blueprints[blueprint.name] = blueprint
        self._blueprint_order.append(blueprint)
    blueprint.register(self, options, first_registration)

如上,在app的blueprints和_blueprint_order属性中添加蓝图对象,同时蓝图调用register方法初始化。

第四步:加载请求钩子

请求钩子常用的有五种,它们通过装饰器的方式添加到app相应的存储字典中。

  • before_first_request:在处理第一个请求前运行。
  • before_request:在每次请求前运行。
  • after_request:如果没有未处理的异常抛出,在每次请求后运行。
  • teardown_request:在每次请求后运行,即使有未处理的异常抛出。
  • teardown_appcontext:在每次请求结束后应用上下文被弹出时执行,即appcontext调用pop方法;
@app.before_request
def test():
    pass

第五步:加载视图函数

app通过route装饰器加载视图函数,将标识符和视图函数作为键值对加入app的view_functions字典属性中。

@app.route(‘/test3‘, endpoint=‘mytest‘)
def test3():
    return ‘ok‘

route装饰器调用了app.add_url_rule(rule, endpoint, f, **options)方法,主要源码步骤为:

def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    ...
    rule = self.url_rule_class(rule, methods=methods, **options) # 创建一个Rule对象
    。。。
    self.url_map.add(rule) # 在app的url_map属性即Map对象中加入rule对象
    。。。
    self.view_functions[endpoint] = view_func # 在app的view_functions属性中加入标识符和视图函数的键值对

第六步:加载错误处理方法

app通过errorhandler装饰器加载对应的错误或状态码相应的处理方法。

@app.errorhandler(400)
def handle_errer(errer):
    print(errer)
    return errer

# 其主要源码
def _register_error_handler(self, key, code_or_exception, f):
    # 可以传入状态码或我们自定义的异常
    exc_class, code = self._get_exc_class_and_code(code_or_exception)
    handlers = self.error_handler_spec.setdefault(key, {}).setdefault(code, {})
    handlers[exc_class] = f

总结

  • flask框架的核心对象有:

    Flask,AppContext,Map, RequestContext,Request,Response,Rule,Blueprint,session,_AppCtxGlobals;

  • Flask主要管理着AppContext,RequestContext,以及所有的请求的处理步骤;
  • AppContext为应用上下文对象,主要管理app对象的获取和请求的临时状态存储变量g;
  • RequestContext为请求上下文,主要管理Request对象和保存会话的session对象;
  • Request为请求对象,在发生请求是随着RequestContext被创建而创建,管理着请求数据和Rule对象;
  • Response为响应对象,在应用逻辑处理完毕后创建,管理着响应数据和响应方法;
  • Rule路由对象,管理着路由和视图处理函数的标识符的对应关系;
  • Map对象管理着所有的标识符和其视图函数对象的一一对应关系;
  • Blueprint对象,Flask对象的缩小版,主要是为了对大量的视图函数做分类管理;
  • session为保存会话信息的容器,可以看做一个字典;
  • _AppCtxGlobals即g变量,用来在每次请求中临时存储资源,它属于应用上下文的一个属性。

参考:

  • https://dormousehole.readthedocs.io/en/latest/config.html
  • http://www.pythondoc.com/flask/config.html

原文地址:https://www.cnblogs.com/cwp-bg/p/9917203.html

时间: 2024-10-30 15:38:32

flask基础之app初始化(四)的相关文章

flask基础之请求处理核心机制(五)

前言 总结一下flask框架的请求处理流程. 系列文章 flask基础之安装和使用入门(一) flask基础之jijia2模板使用基础(二) flask基础之jijia2模板语言进阶(三) flask基础之app初始化(四) WSGI协议 一般来说http服务器和框架需要进行解耦,http专门负责接受HTTP请求.解析HTTP请求.发送HTTP,响应请求等:而web框架负责处理请求的逻辑,和数据库的交互等等,那么它们之间需要约定一套接口使得http服务器能够调用web框架的处理逻辑,这个协议就是

flask基础之AppContext应用上下文和RequestContext请求上下文(六)

前言 应用上下文和请求上下文存在的目的,官方文档讲的很清楚,可参考: http://www.pythondoc.com/flask/appcontext.html 应用上下文对象在没有请求的时候是可以单独存在的,但是请求上下文对象只有在收到请求后才会被创建.请求处理和应用上下文和请求上下文的关系是: 接收请求-->创建请求上下文-->请求上下文入栈-->创建该请求的应用上下文-->应用上下文入栈-->处理逻辑-->请求上下文出栈-->应用上下文出栈 系列文章 fl

【视频】零基础学Android开发:蓝牙聊天室APP(四)

零基础学Android开发:蓝牙聊天室APP第四讲 4.1 ListView控件的使用 4.2 BaseAdapter详解 4.3 ListView分布与滚动事件 4.4 ListView事件监听器:OnItemClickedListener 在线收看:http://www.3g-edu.org/news/video026.htm 视频下载:http://pan.baidu.com/s/1jGkjDGE

Flask 基础知识一

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器. "微"(micro) 并不表示你需要把整个 Web 应用塞进单

Flask 【第二篇】Flask基础

知识点回顾 1.flask依赖wsgi,实现wsgi的模块:wsgiref,werkzeug,uwsgi 2.实例化Flask对象,里面是有参数的 app = Flask(__name__,template_folder='templates',static_url_path='/xxxxxx') 3.两种添加路由的方式 方式一: @app.route('/xxxx') # @decorator def index(): return "Index" 方式二: def index():

flask框架----flask基础

知识点回顾 1.flask依赖wsgi,实现wsgi的模块:wsgiref,werkzeug,uwsgi 2.实例化Flask对象,里面是有参数的 app = Flask(__name__,template_folder='templates',static_url_path='/xxxxxx') 3.两种添加路由的方式 方式一: @app.route('/xxxx') # @decorator def index(): return "Index" 方式二: def index():

【零基础学习App嵌入广告】【01-开篇】

[零基础学习App嵌入广告][01-开篇] 本文目录 一.什么是App广告 二.学习App广告的目的 三.App广告常用术语 四.App广告分类 一.什么是App广告 App广告是指智能手机和平板这类移动设备中第三方应用程序内置广告.广告投放商找广告平台投放广告,平台再把广告让开发者展示,从而形成了App广告的产业链. 二.学习App广告的目的 在移动App的世界里,免费才是王道,很多人不愿意花钱购买程序,因此开发者不得不寻求其他的途径赚钱,目前免费下载+App广告是开发者最主要的盈利模式,因此

C#基础知识篇(四)-----------C#笔记

一.类 1. 什么叫做类? 类是具有相同特征的一类事物统称.所以类是一种抽象,即不是一个实体(我们把类看做模板). 2. 什么叫做对象? 对象是根据类的模板创造出来的一个实体,它具有类里所有的特征,一个也多不得,一个也少不得.少了就不叫这个类的成员了,多了也不是!假如张三有变身这个功能,那么张三就不属于人. 记住对象是根据模板创建的,模板有什么它就有什么,不会多也不会少! 3. 什么叫做字段(或者是成员变量)? 我们把定义在方法的外面,类的里面(即:类中)的变量称之为字段或者说是成员变量. 4.

《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误

http://blog.csdn.net/aqi00/article/details/72907534 http://blog.csdn.net/aqi00/article/details/73065392 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 资源下载 下面是<Android Studio开发实战 从零基础到App上线>一书用到的工具和代码资源:1.本书使用的Android Studio版本为2.2.3,因为Android官网现在不提供该版本的下载,所以博主