5.Flask:请求和响应

Flask(请求和响应 五)

路由设计

前后端不分离,模版渲染

建议:一个视图函数写一个url

  1. 获取所有的项目:/projects def list_projects()
  2. 获取单个项目内容:/project/<id> def get_project()
  3. 修改某个项目内容:/project_edit/<id> def edit_project()

    前后端分离,通过method

/project 类的视图

  • GET 获取单个资源 /project/<id>

  • GET获取全部/projects

  • PUT:修改资源

  • POST:创建资源

  • DELETE:删除资源

一个简单的ajax例子

html

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<p onclick="send_ajax()">点击发送</p>
<script>
function send_ajax() {
$.ajax({
url: "http://127.0.0.1:5000",
data: JSON.stringify({username: "zhongxin"}),
dataType: 'json',
type: "POST",
contentType: 'application/json',
success: function (data) {
alert('成功')
}
})
}
</script>
</body>
</html>

python

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

app = Flask(__name__)


@app.route('/',methods=['GET','POST'])
def index():
if request.method == 'GET':
return render_template('index.html')
elif request.method == 'POST':
print(request.json)
return '成功'


if __name__ == '__main__':
app.run()

测试

使用ajax会返回X-Requested-With: XMLHttpRequest可以在XHR中找到

XHR

request

1
from flask import request

request中包含了全部的请求信息和环境信息

request

values

  • form
  • args

cookies

请求的cookies,dict类型

data

包含了请求数据,并转换成字符串,无法处理的mimetype则会转换成stream

stream

如果请求的表单无法解码,则会无改动的保存到这里。

当请求数据转换string时,使用data是最好的方式,这个stream只返回数据一次

headers

请求头,dict类型

files

通过POST或者PUT请求上传的文件

environ

WSGI隐含的环境配置

method

请求方式

remote_addr

远程IP

user-agent

提供反扒和恶意攻击

文件上传

增加文件类型限制,文件大小限制

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
34
35
36
37
38
39
40
41
import os
from flask import Flask, request, render_template, send_from_directory

app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 10 # 最大上传文件大小


@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'GET':
return render_template('index.html')
elif request.method == 'POST':
print(request.json)
return '成功'


def allowed_format(filename):
if os.path.splitext(filename)[-1].lower() not in ['jpg', 'png']:
return False
else:
return True


@app.route('/upload', methods=['GET', 'POST'])
def upload():
file = request.files.get('pic')
if file is None:
return render_template('index.html')
if allowed_format(file.filename):
file.save(file.filename)
return '保存成功'
return '保存失败'


@app.route('/upload/<filename>')
def get_upload(filename):
return send_from_directory(os.getcwd(), filename)


if __name__ == '__main__':
app.run()
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<p onclick="send_ajax()">点击发送</p>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="pic">
<input type="submit">
</form>
<script>
function send_ajax() {
$.ajax({
url: "http://127.0.0.1:5000",
data: JSON.stringify({username: "zhongxin"}),
dataType: 'json',
type: "POST",
contentType: 'application/json',
success: function (data) {
alert('成功')
}
})
}
</script>
</body>
</html>

上传文件1

如果文件中存在空格,则可能出现问题

保存的时候需要添加secure_filename

1
2
from werkzeug.utils import secure_filename
file.save(secure_filename(file.filename))

响应头

为了返回一个json格式的内容,需要构造一个响应头信息

方式一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import json

from flask import Flask

app = Flask(__name__)


@app.route('/')
def index():
# 构造一个响应头信息
return json.dumps({"username": "zhongxin"}), 201, {"content-type": "application/json"}


if __name__ == '__main__':
app.run()

方式二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import json

from flask import Flask, make_response

app = Flask(__name__)


@app.route('/')
def index():
r = make_response(json.dumps({"username": "zhongxin1"}), {"content-type": "application/json"})
return r


if __name__ == '__main__':
app.run()

查看make_response的源码:

1
2
3
4
5
6
def make_response(*args):
if not args:
return current_app.response_class()
if len(args) == 1:
args = args[0]
return current_app.make_response(args)

当没有入参的时候进入current_app.response_class()

进入之后可以看到response_class = Response

1
2
3
4
5
6
7
8
9
10
11
class Response(ResponseBase, JSONMixin):
default_mimetype = "text/html"

def _get_data_for_json(self, cache):
return self.get_data()

@property
def max_cookie_size(self):
if current_app:
return current_app.config["MAX_COOKIE_SIZE"]
return super(Response, self).max_cookie_size

所以默认的响应头就是"text/html"

方式三

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

app = Flask(__name__)


@app.route('/')
def index():
r = jsonify({"username": "zhongxin2"})
return r


if __name__ == '__main__':
app.run()

可以看一下jsonify源码,其实也就是用的make_response中的 current_app.response_class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def jsonify(*args, **kwargs):
indent = None
separators = (",", ":")

if current_app.config["JSONIFY_PRETTYPRINT_REGULAR"] or current_app.debug:
indent = 2
separators = (", ", ": ")

if args and kwargs:
raise TypeError("jsonify() behavior undefined when passed both args and kwargs")
elif len(args) == 1: # single args are passed directly to dumps()
data = args[0]
else:
data = args or kwargs

return current_app.response_class(
dumps(data, indent=indent, separators=separators) + "\n",
mimetype=current_app.config["JSONIFY_MIMETYPE"],
)
 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
您的支持将鼓励我继续创作!