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 匹配一系列给定值中的一个元素
uuid UUID字符串
  • 规则:<转换器:变量名>,例如:<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状态码用来表示请求处理的结果
类型 状态码 原因短语 说明
成功 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. 重定向

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