app = Flask(__name__)

1.创建static文件夹

static_path = '/static' # 在flask类中# 所有的instance都共享flask class中的static_path
if self.static_path is not None: # 若果静态文件存在,则通过ShareDatMiddleware设置静态文件夹self.url_map.add(Rule(self.static_path + '/<filename>',build_only=True, endpoint='static')) # 添加静态文件urltarget = os.path.join(self.root_path, 'static') # 如果是主程序则拼贴`static`的路径self.wsgi_app = SharedDataMiddleware(self.wsgi_app, { # 添加中间件self.static_path: target # ??})

2.url_for

def url_for(endpoint, **values):return _request_ctx_stack.top.url_adapter.build(endpoint, values)

3.flash

# 模块中的方法
def flash(message):session['_flashes'] = (session.get('_flashes', [])) + [message]# 模块中的方法
def get_flashed_messages():flashes = _request_ctx_stack.top.flashesif flashes is None: # _request_ctx_stack_request_ctx_stack.top.flashes = flashes = \session.pop('_flashes', [])return flashes

4.获得app.py路径,无论在哪运行都能找到app.py工程

self.package_name = package_name
self.root_path = _get_package_path(self.package_name)def _get_package_path(name):return os.path.abspath(os.path.dirname(sys.modules[name].__file__))

5.视图函数 与 路由规则

self.view_functions = {}
self.url_map = Map()def route(self, rule, **options): # 路由处理def decorator(f):self.add_url_rule(rule, f.__name__, **options) # 给url起名字self.view_functions[f.__name__] = f # 给view_function起相同的名字return freturn decorator
# 在我们写入
# @app.route("./index")
# def index():
# 时调用此装饰函数,将它加入到视图函数与路由规则中def add_url_rule(self, rule, endpoint, **options): # 添加URL_RULEoptions['endpoint'] = endpointoptions.setdefault('methods', ('GET',))self.url_map.add(Rule(rule, **options))

6.预处理函数

self.before_request_funcs = []def before_request(self, f):"""Registers a function to run before each request."""self.before_request_funcs.append(f)return f# 当我们在写入
# @before_request
# def somefunc():
# 时调用此装饰函数,将它加入到预处理函数列表中

7.后处理函数

self.after_request_funcs = []
def after_request(self, f):self.after_request_funcs.append(f)return f
# 同6、7,主要用于

8.错误处理函数+

self.error_handlers = {}def errorhandler(self, code):def decorator(f):self.error_handlers[code] = freturn freturn decorator

9.jinja渲染

#1在视图函数中调用,返回jinja模板
def render_template(template_name, **context): # modulecurrent_app.update_template_context(context) # current只能在线程中使用return current_app.jinja_env.get_template(template_name).render(context)#1.1更新上下文,将方法传入页面,所以我们可以在jinja模板中直接使用request等
def update_template_context(self, context): #更新template 上下文reqctx = _request_ctx_stack.topfor func in self.template_context_processors:context.update(func())self.template_context_processors = [_default_template_ctx_processor]
def _default_template_ctx_processor():reqctx = _request_ctx_stack.topreturn dict(request=reqctx.request,session=reqctx.session,g=reqctx.g)#1.2返回jinja
self.jinja_env = Environment(loader=self.create_jinja_loader(),**self.jinja_options) # 配置jinjia2
self.jinja_env.globals.update(url_for=url_for,get_flashed_messages=get_flashed_messagesjinja_options = dict(  autoescape=True,extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_']
)
def create_jinja_loader(self): # 添加jinja2的载入,默认是`templates` # 实例方法if pkg_resources is None:return FileSystemLoader(os.path.join(self.root_path, 'templates'))return PackageLoader(self.package_name)#2.此外添加jinjia文本渲染的方法,有默认值
@app.app_context_processor
def admin_email()def context_processor(self, f): # 添加context_processorsself.template_context_processors.append(f)return f

7.请求处理:

#1 当我们调用app.run()时本质调用了sun_simple()
def run(self, host='localhost', port=5000, **options):from werkzeug import run_simpleif 'debug' in options:self.debug = options.pop('debug')options.setdefault('use_reloader', self.debug)options.setdefault('use_debugger', self.debug)return run_simple(host, port, self, **options)#2 run_simple中第3个三参数是self,既app本身,既app中的__call__方法
# __call__方法返回了wsgi_app()
def __call__(self, environ, start_response):return self.wsgi_app(environ, start_response)#3 wsgi_app
def wsgi_app(self, environ, start_response): # 真实的WSGI application,在__call__中调用with self.request_context(environ):rv = self.preprocess_request() # 首先调用预处理请求函数if rv is None: # 如果预处理后,返回为None,??rv = self.dispatch_request() # 这时可能返回字符串,也可能是responseclassresponse = self.make_response(rv) # 进一步处理,比如如果是response = self.process_response(response) # 保存sessionreturn response(environ, start_response)
#3.1 首先打开了上下文request_context(environ)
def request_context(self, environ):return _RequestContext(self, environ)# 返回的是_RequestContext对象,这对象存放了
# app
# url_adapter 绑定了environ,所以可以调用match来根据url获得endpoints,继而获得function
# request 获得当前environ对应的request instance
# session 获得当前session,其实就是cookie
# g _RequestGlobals()
class _RequestContext(object): # 使用with语句,拿到栈顶的request进行处理def __init__(self, app, environ):self.app = app # 当前的appself.url_adapter = app.url_map.bind_to_environ(environ) # 主要用来处理URL,因为绑定了environ以后就不需要再往match里传递参数了self.request = app.request_class(environ) # 当前的请求信息self.session = app.open_session(self.request) # 当前的会话信息 secret_key = None 类中设定,所有app共享self.g = _RequestGlobals() # ?这个地方还没写self.flashes = None # ?这个地方也没写
# 载入上下文时,将当前的app 压入_request_ctx_stack 栈中def __enter__(self): # 使用with语句_request_ctx_stack.push(self) # 将当前请求推入栈
# 离开上下文时,将当前的app 弹出栈def __exit__(self, exc_type, exc_value, tb):# do not pop the request stack if we are in debug mode and an# exception happened.  This will allow the debugger to still# access the request object in the interactive shell.if tb is None or not self.app.debug:_request_ctx_stack.pop() # 将往前请求推出栈#3.2 调用preprocess_request()方法进行请求预处理,返回rule和values
def preprocess_request(self):for func in self.before_request_funcs:rv = func()if rv is not None: # 这里不需要判断,因为在调用preprocess_request,后又做了判断return rv#3.3 如果preprocess_request()返回为None,则调用dispatch_request,用我们定义的视图函数来处理。比如验证是否登录。
def dispatch_request(self):try:endpoint, values = self.match_request()return self.view_functions[endpoint](**values)except HTTPException, e:handler = self.error_handlers.get(e.code)if handler is None:return ereturn handler(e)except Exception, e:handler = self.error_handlers.get(500)if self.debug or handler is None:raisereturn handler(e)#3.4 调用make_response,该方法强制将rv转换成response对象
def make_response(self, rv):if isinstance(rv, self.response_class):return rvif isinstance(rv, basestring):return self.response_class(rv)if isinstance(rv, tuple):return self.response_class(*rv)return self.response_class.force_type(rv, request.environ)#3.5 调用process_response,在response对象返回给WSGI server之前,进行操作,比如设置session等,返回值还会受到.after_request_funcs操作。
def process_response(self, response):session = _request_ctx_stack.top.sessionif session is not None:self.save_session(session, response)for handler in self.after_request_funcs:response = handler(response)return response#存储session
# 在_RequestContext调用oepn_sesion方法获得session,实际调用的是SecureCookie,既存储在cookie中self.session = app.open_session(self.request)
def open_session(self, request): # 会话,通过cookie来实现key = self.secret_keyif key is not None:return SecureCookie.load_cookie(request, self.session_cookie_name,secret_key=key)
def save_session(self, session, response):if session is not None: # 如果不为空,则更新sessionsession.save_cookie(response, self.session_cookie_name)session_cookie_name = 'session' # Flask类中定义 所有app共享

参考:
理解current
需要注意的是current_app是“线程”本地变量,所以current_app需要在视图函数或命令行函数中使用,否则也会报错。
https://blog.csdn.net/JENREY/article/details/86606653

flask v0.1 执行流程 Flask(__name__)相关推荐

  1. flask v0.1 内部运行程序

    Werkzeug is an HTTP and WSGI utility library for Python.提供: 1.WSGI server 类似于tomcat,是一个server 容器 2.对 ...

  2. python flask 路由_python框架之Flask(2)-路由和视图Session

    路由和视图 这一波主要是通过看源码加深对 Flask 中路由和视图的了解,可以先回顾一下装饰器的知识:[装饰器函数与进阶] 路由设置的两种方式 #示例代码 from flask importFlask ...

  3. flask 第八篇 实例化flask时的参数配置

    Flask 是一个非常灵活且短小精干的web框架 , 那么灵活性从什么地方体现呢? 有一个神奇的东西叫 Flask配置 , 这个东西怎么用呢? 它能给我们带来怎么样的方便呢? 首先展示一下: from ...

  4. Flask后端实践 连载十三 Flask输出Excel报表

    Flask后端实践 连载十三 Flask输出Excel报表 tips: 简单实现Flask输出Excel报表 本文基于python3编写 代码仓库 项目场景 由于项目是工程上的使用,不仅需要对采集的数 ...

  5. djangorestframework源码分析2:serializer序列化数据的执行流程

    djangorestframework源码分析 本文环境python3.5.2,djangorestframework (3.5.1)系列 djangorestframework源码分析-serial ...

  6. djangorestframework源码分析1:generics中的view执行流程

    djangorestframework源码分析 本文环境python3.5.2,djangorestframework (3.5.1)系列 djangorestframework源码分析-generi ...

  7. python 装饰器实现缓存_Python, 这一个缓存装饰器, 其执行流程是怎样的?

    2017/2/6 描述 比如, 考虑这样一段代码, 它的执行流程是怎样的呢 ? class Foo(object): @cached_property def foo(self): # calcula ...

  8. flask tutorial = make a blog :) flask 搭建博客系统从零开始!

    please follow the tutorial from the official site :) http://flask.pocoo.org/docs/ You could download ...

  9. python flask高级编程之restful_python Flask实现restful api service

    一直在用node.js做后端,要逐步涉猎大数据范围,注定绕不过python,因此决定把一些成熟的东西用python来重写,一是开拓思路.通过比较来深入学习python:二是有目标,有动力,希望能持之以 ...

最新文章

  1. HEALTHY LIFE OPENCART 自适应主题模板 ABC-0133
  2. Ureport2源码修改
  3. ceph-rest-api_快速检查REST API是否有效的方法-从清单文件中获取详细信息
  4. 卷积神经网络 手势识别_如何构建识别手语手势的卷积神经网络
  5. [线性代数]Note 1--方程组的几何解释
  6. 格子游戏(信息学奥赛一本通-T1347)
  7. 七彩虹智能主板设置U盘启动教程
  8. rubyonrails安装
  9. Ubuntu安装谷歌拼音输入法
  10. 会议主视觉_揭秘!2018杭州云栖大会主视觉设计——光锥之内皆命运
  11. 神仙打架!传言阿里 P10 赵海平被 P11 多隆判定 3.25 离职,如何评价阿里 P10 赵海平对王垠的面试?...
  12. T-test检验中的P,α理解
  13. STM32F7--->SDRAM
  14. UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xbd in position 115: illegal multibyte sequence
  15. Meld——目录文件对比工具
  16. ios播放本地声音文件
  17. 2019版云计算大数据学习路线图(含大纲+视频+工具+书籍+面试)
  18. 关于安卓的通知栏 NotificationCompat
  19. docker pdf 中文版 linux,Docker入门实战手册PDF
  20. 万能实用工具箱微信小程序

热门文章

  1. MySQL用函数统计记录总数_在mysql中使用COUNT 或者SUM函数计算记录总数
  2. Python之网络爬虫(爬虫基本认知、网络爬虫之路)
  3. Python+pandas绘制平行坐标图
  4. 学会提问,你就成功了一大半!
  5. Python+tkinter不允许退出程序的思路和实现
  6. linux mysql5.7.18多实例_mysql5.7.13二进制包安装多实例
  7. 奖励名单表格模板_“我用一套表格,解决了孩子的拖延症,一路用到小学高年级!”...
  8. 手写 Object.create
  9. python中 tolist_python 列表,数组,矩阵两两转换tolist()的实例
  10. map语法获取index_python获取慧聪企业信息