请求与响应 模板[使用方法+源码剖析]
HTTP请求类型
在上一期的最后我们提到了注册路由时的参数,有一个比较重要的参数没有提到:methods,即请求方式,详细介绍methods之前先温习一下HTTP请求方式。
在最新的HTTP/1.1参考意见稿RFC7231(原在RFC2616)中定义了如下几种请求方式。
https://tools.ietf.org/html/rfc7231
请求方式 | 详细介绍 |
---|---|
GET | 向特定目标资源发出请求,是信息检索的主要机制。 |
HEAD | HEAD方法与GET类似,不同之处在于服务器在响应中不得发送消息正文,服务器应发送与HEAD请求相同的报头字段。 |
POST | 向指定资源提交数据进行处理请求。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。 |
PUT | 更新指定位置的资源文件。与POST的区别是PUT是幂等的,多次调用同一个PUT请求将始终产生相同的结果。而反复调用POST请求会多次创建相同的资源。 |
DELETE | 请求原始服务器删除目标资源与其当前功能之间的关联。即删除所标识的资源。 |
CONNECT | 请求接收者建立到由请求目标标识的目的源服务器的隧道。 |
TRACE | 回显服务器收到的请求 |
而在实际应用中主要用到的请求方式有GET POST HEAD PUT DELETE
Flask 请求
注册路由时通过配置methods参数来指定HTTP请求类型。
1 | from flask import Flask |
使用表单以POST方式访问路由
login.html
1 | <!DOCTYPE html> |
对应后端
1 | @app.route('/login', methods=['POST', 'GET']) |
访问login.html,表单中填写信息提交后的结果
这里代码中用到的request对象其实是LocalProxy实例而来,在后边上下文章节中会详细分析LocalProxy,这里先了解一些request包含的属性。
request.form POST请求时的表单,request.form.get(‘username’)获取表单中username的值。
request.args GET请求时的参数,request.args.get(‘username’)获取url中username参数的值。
request.headers 获取请求头。
request.cookies 获取请求的cookies
request.files 获取上传的文件
request.method 获取请求的方法(GET/POST)
request.scheme 获取请求的协议(http)
request.path 获取请求相对路径(/login)
request.url 获取请求的url(http://localhost:5000/login)
Flask 响应
定义路由的视图函数时,return的对象/值 即为响应,之前接触到返回的类型大致有以下三种:
- 返回一个字符串 return ‘success’
- 返回渲染的模板 return render_template(‘xxx.html’)
- 返回重定向路由 return redirect(‘/index’)
除了上述三种情况外,我们也可以自定义response对象。
1 | # 自定义返回响应头 |
简述了flask中从请求到响应的使用方法,我们再从源码的角度分析下该过程(只给出与本节内容相关的代码,并去除了try except等不影响大体流程的代码)。
1.通过 call 方法将 Flask 对象变为可调用
1 | def __call__(self, environ, start_response): |
2.实现 wsgi_app 函数处理 web 服务器转发的请求
1 | def wsgi_app(self, environ, start_response): |
3.full_dispatch_request 先大喊一声请求来了,并执行3.1 3.2中内容
1 | request_started.send(self) |
3.1. rv = self.dispatch_request(),根据收到的请求到路由与视图函数对应关系中找到符合的,并返回视图函数
1 | return self.view_functions[rule.endpoint](**req.view_args) |
3.2. return self.finalize_request(rv) 设置响应,再大喊一声请求结束了,并返回响应
1 | response = self.make_response(rv) |
模板
在前面的实例中,视图函数的主要作用是生成请求的响应,这是最简单请求。实际上,视图函数有两个作用:
处理业务逻辑
返回响应内容
在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本。
模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
使用真实值替换变量,再返回最终得到的字符串,这个过程称为’渲染’
Flask 是使用 Jinja2 这个模板引擎来渲染模板
使用模板的好处
视图函数只负责业务逻辑和数据处理(业务逻辑方面)
而模板则取到视图函数的数据结果进行展示(视图展示方面)
代码结构清晰,耦合度低
在这里不过多关注Jinjia2本身的特性,只关注其与flask有关的功能。
变量取值 { { } }
注释 { # # }
控制结构
1 | {% if 'lockcy' in names %} |
循环结构
1 | {% for name in names %} |
宏定义
1 | {% macro button(value) %} |
上述代码输出的结果如下:
过滤器
过滤器通过管道符号|与变量链接,并且可以通过圆括号传递参数,如:
1 | {# 单词首字母大写 #} |
Jinjia2过滤器比较多,详细内容可以参考 https://www.cnblogs.com/liuruitao/p/7787482.html
参考资料
[1]RFC7231:https://tools.ietf.org/html/rfc7231
[2]Jinjia2模板设计者文档:http://docs.jinkan.org/docs/jinja2/templates.html
[3]Jinjia2过滤器:https://www.cnblogs.com/liuruitao/p/7787482.html