Flask - request、response - 请求、响应

目录

一、request 请求相关属性

二、 response、后台return的数据形式

2-1 基于return方式 生成的response对象 的修改操作

三、request 请求扩展

3-1 @before_request - 收到请求前执行绑定函数

3-2 @after_request - 每个请求后执行绑定函数,若请求异常不执行

3-3 @before_first_request - 第一次请求时触发函数执行

3-4 @teardown_request - 每个请求后执行绑定函数,若请求异常照常执行

3-5 @errorhandler - 根据错误状态码自定义返回

3-6 @template_global - 模板的标签使用

3-7 @template_filter - 模板过滤器使用

四、中间件

4-1 中间件实现方式

4-2 源码分析

五、请求上下文源码分析 - 请求流程解析


一、request 请求相关属性

  • request.method  - 请求的方式
  • request.args  - get方式提交的数据,即URL内包含的数据信息
    • request.args.get('key', )
  • request.form  - Post方式提交的数据,字典形式存储获取
  • request.values - CombinedMultiDict 字典形式存储,内容是formargs。 可以使用values替代form和args。
  • request.cookies  - 请求的cookies,类型是dict
  • request.stream - 在可知的mimetype下,如果进来的表单数据无法解码,会没有任何改动的保存到这个·stream·以供使用。很多时候,当请求的数据转换为string时,使用data是最好的方式。这个stream只返回数据一次。
  • request.headers - 请求头,字典形式,结果以list形式返回
  • request.data - 包含了请求的数据,并转换为字符串,除非是一个Flask无法处理的mimetype。
  • 用户请求路径获取方式(例如 :http://www.example.com/myapplication/page.html?x=y )
  • request.files - MultiDict,带有通过POST或PUT请求上传的文件。
    • obj = request.files['the_file_name']
      obj.save('/var/www/uploads/' + secure_filename(f.filename))
  • request.environ - WSGI隐含的环境配置。
  • request.is_xhr  - 如果请求是发送到一个实际的模块,则该参数返回当前模块的名称。这是弃用的功能,使用blueprints替代。
  • request.blueprint  - 蓝图名字
  • request.endpoint - endpoint匹配请求,这个与view_args相结合,可是用于重构相同或修改URL。当匹配的时候发生异常,会返回None。
  • request.json - 如果mimetypeapplication/json,这个参数将会解析JSON数据,如果不是则返回None。 
    可以使用这个替代get_json()方法。
  • request.max_content_length - 只读,返回MAX_CONTENT_LENGTH的配置键。
  • request.module  - 如果请求是发送到一个实际的模块,则该参数返回当前模块的名称。这是弃用的功能,使用blueprints替代。

二、 response、后台return的数据形式

  • return "字符串" - 字符串形式
  • return render_template('html模板路径',**{}) - 将数据递交给指定模板
  • return redirect('/index.html') - 重定向页面
  • return jsonify({'k1':'v1'}) - 返回json数据

2-1 基于return方式 生成的response对象 的修改操作

from flask import make_response,jsonify

# 生成response对象,用于往内进行添加操作 - 三种实现方式
# response是flask.wrappers.Response类型
response = make_response("字符串")
response = make_response(render_template('index.html'))
response = make_response(redirect('/index.html'))
response = make_response(jsonify({'k1':'v1'}))

# 对response进行cookie操作,删除写入cookie值
response.delete_cookie('key')
response.set_cookie('key', 'value')
response.headers['X-Something'] = 'A value'

return response

三、request 请求扩展

!!注意点总结!!

  • 执行流程
    • @before_request 包裹函数1,函数2
    • 请求的执行
    • @after_request 包裹函数2,函数1
  • 若 @before_request 或者@after_request 包裹函数内存在return返回值,之后其他被 after_request包裹的函数照常执行。

3-1 @before_request - 收到请求前执行绑定函数

类比django中间件中的process_request,在请求收到之前绑定一个函数做一些事情

# 基于before_request的用户登录认证
@app.before_request
def process_request(*args,**kwargs):
    if request.path == '/login':
        return None
    user = session.get('user_info')
    if user:
        return None
    return redirect('/login')

3-2 @after_request - 每个请求后执行绑定函数,若请求异常不执行

类比django中间件中的process_response,每一个请求之后绑定一个函数,如果请求没有异常

@app.after_request
def process_response1(response):
    print('process_response1 执行')
    return response

3-3 @before_first_request - 第一次请求时触发函数执行

@app.before_first_request
def first():
    pass

3-4 @teardown_request - 每个请求后执行绑定函数,若请求异常照常执行

@app.teardown_request 
def ter(e):
    pass

3-5 @errorhandler - 根据错误状态码自定义返回

路径不存在时404,服务器内部错误500

@app.errorhandler(404)
def error_404(arg):
    return "404错误了"

3-6 @template_global - 模板的标签使用

@app.template_global()
def sb(a1, a2):
    return a1 + a2
#{{sb(1,2)}}

3-7 @template_filter - 模板过滤器使用

@app.template_filter()
def db(a1, a2, a3):
    return a1 + a2 + a3
#{{ 1|db(2,3)}}

四、中间件

4-1 中间件实现方式

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World!'

# 模拟中间件
class Md(object):
    def __init__(self,old_wsgi_app):
        self.old_wsgi_app = old_wsgi_app

    def __call__(self,  environ, start_response):
        print('开始之前')
        ret = self.old_wsgi_app(environ, start_response)
        print('结束之后')
        return ret

if __name__ == '__main__':
    # 将原wsgi_app作为参数传入,即替换操作
    app.wsgi_app = Md(app.wsgi_app)
    app.run()

4-2 源码分析

每次执行Flask对象时,本质上是调用了对象的__call__方法。

即,在__call__方法return前执行的逻辑为请求未开始前最开始的部位,return后执行的逻辑为最末尾的执行。

所以中间件的实现方式,重写Flask对象的__call__方法,将前后逻辑包裹在 wsgi_app(environ, start_response) 的执行前后。

五、请求上下文源码分析 - 请求流程解析

程序运行,两个LocalStack()对象,一个里面放request和session,另一个放g和current_app

'''第一阶段:将ctx(request,session)放到Local对象上'''

'''第二阶段:视图函数导入:request/session'''
request.method
    -LocalProxy对象.method,执行getattr方法,getattr(self._get_current_object(), name)
        -self._get_current_object()返回return self.__local(),self.__local(),在LocakProxy实例化的时候,object.__setattr__(self, '_LocalProxy__local', local),此处local就是:partial(_lookup_req_object, 'request')

    -def _lookup_req_object(name):
        top = _request_ctx_stack.top #_request_ctx_stack 就是LocalStack()对象,top方法把ctx取出来
        if top is None:
            raise RuntimeError(_request_ctx_err_msg)
        return getattr(top, name)#获取ctx中的request或session对象

'''第三阶段:请求处理完毕'''
    - 获取session并保存到cookie
    - 将ctx删除

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/87626439