Flask Web学习笔记之Flask与HTTP
2.1 请求响应循环
- 每一个Web应用都包含这种处理模式:客户端发出请求,服务器端处理请求并返回响应
- HTTP是客户端和服务器端沟通的桥梁,当用户点击URL时,浏览器会生成http请求,经互联网发送到对应的web服务器,Web服务器端接收请求,通过WSGI将HTTP格式数据转换成能用的数据,并生成响应又依次返回给客户端
2.2 HTTP请求
2.2.1 报文
- 常见HTTP方法:GET,POST,PUT,DELETE,HEAD,OPTIONS
2.2.2 Request对象
- 当Flask接收到请求后,请求对象会提供多个属性来获取URL的各个部分,除了URL,请求报文中的其他信息都可以通过request对象提供的属性和方法获取
- 常用属性和方法如:
args
,cookies
,data
,form
,files
,json
,method
,user_agent
,get_json()
等等
2.2.3 在Flask中处理请求
1. 路由匹配
- 程序实例中存储了一个路由表(app.url_map),当请求发来后,Flask会根据请求报文中的URL来尝试与该表中所有的URL规则匹配,调用匹配成功的视图函数。
- 可使用
flask routes
查看路由
2. 设置监听的HTTP方法
- 当查看了路由表后可以发现,每一个路由还包含了一个监听的HTTP方法。
- 我们可以在app.route()装饰器中使用methods参数传入一个包含监听的HTTP方法的可迭代对象。
@app.route('/hello',methods=['GET','POST'])
def hello():
return "<h1>Hello,Flask!</h1>"
- 当请求的方法不符合要求时,请求将无法被正常处理(出现405错误响应),因此我们可以为同一个URL根据请求方式定义多个视图函数
3. URL处理
- URL中的变量部分默认类型是字符串,但Flask提供了一些转换器可以在URL规则中使用
转换器 | 说明 |
---|---|
string | 不包含斜线的字符串(默认值) |
int | 整型 |
float | 浮点数 |
path | 包含斜线的字符串,static路由的URL规则中的filename变量就是使用了这个转换器 |
any | 匹配一系列给定值中的一个元素 |
uuid | UUID字符串 |
- 规则:
<转换器:变量名>
,例如:<int:year>
@app.route('/hello/<int:year>')
def hello():
return '<p>hello,I am %d years old!</p>'%(year-2019)
- 在这个例子中,如果不使用int转换器,默认的string转换器会将其转换成string类型,为了计算数值,需要使用int转换器将变量转换成整型
- 在用法上比较独特的是any转换器,
<any(value1,value2...):变量名>
@app.route('/colors/<any(blue,white,red):color>')
def three_colors(color):
return '<p>You choose %s</p>'%color
2.2.4 请求钩子
- Flask提供一些请求钩子(HOOK),来对请求进行预处理和后处理,它们可以用来注册在请求处理的不同阶段执行的回调函数
钩子 | 说明 |
---|---|
before_first_request | 注册一个函数,在处理第一个请求前运行 |
before_request | 注册一个函数,在处理每个请求前运行 |
after_request | 注册一个函数,如果没有未处理的异常抛出,会在每个请求结束后运行 |
teardown_request | 注册一个函数,即使有未处理的异常抛出,会在每个请求结束后运行。如果发送异常,会传入异常对象作为参数到注册的函数中 |
after_this_request | 在注册函数内注册一个函数,会在这个请求结束后运行 |
@app.before_request
def do_something():
pass #这里的代码会在每个请求处理前执行
2.3 HTTP响应
2.3.1 响应报文
- 响应报文主要由协议版本,状态码(status code),原因短语(reason phrase),响应首部和响应主体组成。
- 响应报文的首部包含一些关于响应和服务器的信息,这些内容由Flask生成,而我们在视图函数中返回的内容即为响应报文中的主题内容
- HTTP状态码用来表示请求处理的结果
类型 | 状态码 | 原因短语 | 说明 |
---|---|---|---|
成功 | 200 | OK | 请求被正常处理 |
201 | Created | 请求被处理,并创建了一个新资源 | |
204 | No Content | 请求处理成功,但无内容返回 | |
重定向 | 301 | Moved Permanently | 永久重定向 |
302 | Found | 临时性重定向 | |
304 | Not Modified | 请求的资源未被修改,重定向到缓存的资源 | |
客户端错误 | 400 | Bad Request | 请求无效,即请求报文中存在错误 |
401 | Unauthorized | 表示请求的资源需要获取授权信息,在浏览器中会弹出认证弹窗 | |
403 | Forbidden | 请求的资源被服务器拒绝访问 | |
404 | Not Found | 服务器上无法找到请求的资源或者URL无效 | |
服务器端错误 | 500 | Internet Server Error | 服务器内部发送错误 |
2.3.1 在Flask中生成响应
- 视图函数可以返回:响应主体,状态码,首部字段
1. 重定向
代码语言:javascript复制from flask import Flask,redirect
@app.route('/hello')
def hello():
return redirect('http://justlovesmile.top')
- redirect函数默认的状态码是302即临时重定向,可以通过code关键字传入或作为第二参数传入修改
- 如果要在程序内重定向到其他视图,只需在redirect函数中使用url_for()函数生成目标URL
from flask import Flask,redirect,url_for
@app.route('/hi')
def hi():
...
return redirect(url_for('hello'))
@app.route('/hello')
def hello():
...
2. 错误响应
- 使用Flask提供的abort()函数,手动返回错误响应
- abort()函数前不需要执行使用return语句,一旦abort函数被调用,其之后的代码不被执行
from flask import Flask,abort
@app.route('/404')
def not_found():
abort(404)
2.3.2 响应格式
- 默认情况下Flask使用html格式响应,在特定情况下,也会使用其他格式,不同的响应数据格式需要设置不同的MIME类型,MIME类型在首部的Content-Type定义,以默认的html类型为例
Content-Type: text/html;charset=utf-8
- 如果想使用其他的MIME类型,可以通过Flask提供的make_response()方法,生成对应响应对象,传入响应的主体作为参数,然后使用响应对象的mimetype属性设置MIME类型
from flask import Flask
from flask import make_response
@app.route('/foo')
def foo():
response=make_response('Hello World')
response.mimetype='text/plain'
return response
- 常用MIME类型:
- 纯文本:
text/plain
- HTML:
text/html
- XML:
application/xml
- json:
application/json
- 纯文本:
- 对于json数据,python的json模块具有
dumps()
和load()
等方法,并且Flask提供了包装好的更方便的jsonify()
函数
from falsk import Flask,make_response,json
@app.route('/foo')
def foo():
data={
'name':'justlovesmile',
'gender':'male'
}
response=make_response(json.dumps(data))
response.mimetype='application/json'
return response
等价于
代码语言:javascript复制from flask import Flask,jsonify
@app.route('/foo')
def foo():
return jsonify({name='justlovesmile',gender='male'})
- jsonify()函数默认返回码为200,可以附加状态码自定义响应类型
@app.route('/foo')
def foo():
return jsonify({name='',gender=''}),500