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方法的可迭代对象。
1
2
3
@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匹配一系列给定值中的一个元素
uuidUUID字符串
  • 规则:<转换器:变量名>,例如:<int:year>
1
2
3
@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...):变量名>
1
2
3
@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在注册函数内注册一个函数,会在这个请求结束后运行
1
2
3
@app.before_request
def do_something():
pass #这里的代码会在每个请求处理前执行

2.3 HTTP响应

2.3.1 响应报文

  • 响应报文主要由协议版本,状态码(status code),原因短语(reason phrase),响应首部响应主体组成。
  • 响应报文的首部包含一些关于响应和服务器的信息,这些内容由Flask生成,而我们在视图函数中返回的内容即为响应报文中的主题内容
  • HTTP状态码用来表示请求处理的结果
类型状态码原因短语说明
成功200OK请求被正常处理
201Created请求被处理,并创建了一个新资源
204No Content请求处理成功,但无内容返回
重定向301Moved Permanently永久重定向
302Found临时性重定向
304Not Modified请求的资源未被修改,重定向到缓存的资源
客户端错误400Bad Request请求无效,即请求报文中存在错误
401Unauthorized表示请求的资源需要获取授权信息,在浏览器中会弹出认证弹窗
403Forbidden请求的资源被服务器拒绝访问
404Not Found服务器上无法找到请求的资源或者URL无效
服务器端错误500Internet Server Error服务器内部发送错误

2.3.1 在Flask中生成响应

  • 视图函数可以返回:响应主体,状态码,首部字段

    1. 重定向

1
2
3
4
5
from flask import Flask,redirect

@app.route('/hello')
def hello():
return redirect('http://justlovesmile.top')
  • redirect函数默认的状态码是302即临时重定向,可以通过code关键字传入或作为第二参数传入修改

  • 如果要在程序内重定向到其他视图,只需在redirect函数中使用url_for()函数生成目标URL

1
2
3
4
5
6
7
8
9
10
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函数被调用,其之后的代码不被执行
1
2
3
4
5
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类型
1
2
3
4
5
6
7
8
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()函数

1
2
3
4
5
6
7
8
9
10
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

等价于

1
2
3
4
5
from flask import Flask,jsonify

@app.route('/foo')
def foo():
return jsonify({name='justlovesmile',gender='male'})
  • jsonify()函数默认返回码为200,可以附加状态码自定义响应类型
1
2
3
@app.route('/foo')
def foo():
return jsonify({name='',gender=''}),500

2.3.3 来一块Cookie