跳转至

请求和响应

一、请求

1.请求方法

1.1 获取formdata中的数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from flask import Flask, render_template, request

app = Flask(__name__)


@app.route('/login', methods=["GET", "POST"])
def login():
    if request.method == "GET":
        return render_template('login.html')
    if request.method == "POST":
        print(request.form)  # ImmutableMultiDict([('username', 'admin'), ('password', '123456')])
        print(request.form.to_dict())  # {'username': 'admin', 'password': '123456'}
        print(request.form.get('username'))  # admin
        return "ok"

1.2 获取请求方法

1
request.method

1.3 获取URL中的参数

1
2
3
request.args  # ImmutableMultiDict([('page', '1')])
request.args.get('page')  # 1
request.args.to_dict()  # {'page': '1'}

1.4 接收文件

创建模板文件接收文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>File</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    <p><input type="file" name="myfile"></p>
    <input type="submit" value="上传">
</form>
</body>
</html>

保存文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from flask import Flask, render_template, request

app = Flask(__name__)


@app.route('/file', methods=["GET", "POST"])
def user():
    if request.method == "GET":
        return render_template('file.html')
    if request.method == "POST":
        print(request.files)  # ImmutableMultiDict([('myfile', <FileStorage: 'George.jpg' ('image/jpeg')>)])
        print(request.files.get('myfile'))  # <FileStorage: 'George.jpg' ('image/jpeg')>
        my_file = request.files.get('myfile')
        my_file.save(my_file.filename)
        return "ok"

1.5 URL相关

1
2
3
4
5
6
7
8
9
request.url           # http://10.0.0.128:5000/user?page=1
request.url_root      # http://10.0.0.128:5000/
request.base_url      # http://10.0.0.128:5000/user
request.host_url      # http://10.0.0.128:5000/
request.url_charset   # utf-8   url编码方式
request.full_path     # /user?page=1
request.host          # 10.0.0.128:5000
request.path          # /user
request.url_rule      # /user

1.6 其他数据

1
2
3
4
request.cookies       # ImmutableMultiDict([('user', 'admin')])
request.headers 
request.data          # b'{"name":"admin"}' Content-Type无法被识别或不包含form字段时,获取请求体中的数据
request.json          # {'name': 'admin'} 获取Content-Type:application/json时提及的数据

2. 请求钩子

1. before_request

每次请求之前运行,运行顺序按代码的顺序执行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from flask import Flask

app = Flask(__name__)
app.config['SECRET_KEY'] = 'UxlucZVeYToAjpMULTNOEw=='


@app.before_request
def before_part1():
    print("请求之前 part1")


@app.before_request
def before_part2():
    print("请求之前 part2")


@app.route('/')
def index():
    print("视图函数")
    return "Hello World"

# 请求之前 part1
# 请求之前 part2
# 视图函数

如果before_request装饰的函数中有return,跳过后续的before_request和视图函数,直接执行after_request

2. before_first_request

程序启动后,只有第一个请求会执行。

3. after_request

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from flask import Flask

app = Flask(__name__)
app.config['SECRET_KEY'] = 'UxlucZVeYToAjpMULTNOEw=='


@app.before_request
def before_part1():
    print("请求之前 part1")
    # 在此处有return ,会跳过视图函数,直接执行after_request
    return "请求之前 part1"


@app.after_request
def after_part1(response):
    print("请求之后 part1")
    return response


@app.after_request
def after_part1(response):
    print("请求之后 part2")
    return response


@app.route('/')
def index():
    print("视图函数")
    return "Hello World"

# 请求之前 part1
# 请求之后 part2
# 请求之后 part1

after_request可以叠加多个,执行顺序按代码顺序倒序执行。

4. teardown_request

二、响应

1. 返回字符串

1
2
3
4
5
6
7
8
from flask import Flask

app = Flask(__name__)


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

2. 返回模板文件

创建模板文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ mkdir templates
$ cd templates/
$ cat index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        Hello World!
    </body>
</html>

此时的目录结构如下:

1
2
3
4
5
$ tree -L 2
.
├── hello.py
├── templates
    └── index.html

使用render_template返回模板文件

1
2
3
4
5
6
7
8
from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')

3. 返回response对象

如果需要返回cookie和请求头等,需要通过make_response()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def index():
    response = make_response("Hello World!")
    response.set_cookie('user', 'admin')
    return response

4. 返回json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from flask import Flask, jsonify

app = Flask(__name__)

data = {
    'user': 'root',
    'group': 'root',
}


@app.route('/')
def index():
    return jsonify(data)

使用curl命令访问

1
2
$ curl -s  http://127.0.0.1:5000/
{"group":"root","user":"root"}

返回的是标准格式的json:Content-Type: application/json

1
2
3
4
5
6
$ curl -I  http://10.0.0.128:5000/
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 31
Server: Werkzeug/1.0.1 Python/3.6.9
Date: Sun, 20 Jun 2021 12:33:56 GMT

5. 重定向

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from flask import Flask, redirect

app = Flask(__name__)


@app.route('/login')
def login():
    return redirect('/')


@app.route('/')
def index():
    return 'Hello World!'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ curl -s -i -L  http://10.0.0.128:5000/login
HTTP/1.0 302 FOUND   # 302重定向
Content-Type: text/html; charset=utf-8
Content-Length: 208
Location: http://10.0.0.128:5000/  # 重定向到/
Server: Werkzeug/2.0.1 Python/3.6.9
Date: Sun, 20 Jun 2021 03:33:27 GMT

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 12
Server: Werkzeug/2.0.1 Python/3.6.9
Date: Sun, 20 Jun 2021 03:33:27 GMT

Hello World!

6. 返回文件

1
2
3
4
5
6
7
8
from flask import Flask, send_file

app = Flask(__name__)


@app.route('/peppa')
def index():
    return send_file('Peppa.jpg')

send_file:打开并返回文件内容。可以自动识别文件类型,在响应头中加入 Content-Type: 文件类型 。文件类型是可以被浏览器识别的,如果内容不能被客户端识别,客户端会执行下载处理。

三、自定义错误页面

通过app.errorhandler装饰器自定义错误页面。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from flask import Flask, render_template

app = Flask(__name__)


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


@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@app.errorhandler(500)
def page_not_found(e):
    return render_template('500.html'), 500