本文最后更新于:2022年7月21日 下午
Flask开发学习笔记
[TOC]
照着这个学的:
2021年史上最强Flask框架 Flask6天速成从入门到精通(无偿分享附赠课件资料)_哔哩哔哩_bilibili
Flask的g对象和钩子函数 - 知乎 (zhihu.com)
Flask教程(十六)RESTful-API - 迷途小书童的Note迷途小书童的Note (xugaoxiang.com)
Hello world
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
| from flask import Flask
app = Flask(__name__)
class DefaultSettings: SECRET_KEY = "ASFG$$#%SDG!GHAxa@%gASD" DEBUG = True
app.config.from_object(DefaultSettings)
@app.route('/') def hello_world(): print(app.config["SECRET_KEY"]) return 'Hello World!'
if __name__ == '__main__': app.run()
|
查询路由
路由就是@app.route('\')
这样的路径,不同页面可以分散在不同的文件。
- 可以使用命令
flask routes
快速查询。
app.url_map
也包含了所有的路由信息。
app.url_map.iter_rules()
也可以用来遍历。
CORS 跨域资源共享
浏览器A从服务器B1中获取了一个网页,这个网页需要显示存放于服务器B2中的广告,这个时候就形成了跨域获取资源,浏览器A出于安全性考虑要对关于进行限制,所以需要使用CORS技术来解决这个问题。解决方法如下:
- 浏览器A先向B2发送
OPTIONS
请求,询问其是否接受来自B1的跨域请求。
- B2返回头中包含
allow-origin 'www.b1.com'
,允许跨域访问。
- 浏览器A向B2发送正式
GET
请求。
请求与响应
指定请求方式
在页面路由中可以指定页面的访问方式,若错误方式访问会405
1
| @app.route("/test1", methods=["GET", "POST"])
|
获取URL路径参数
1 2 3 4 5 6 7 8 9
|
@app.route('/users/<user_id>') def user_info(user_id): print(type(user_id), user_id) return str(user_id)
|
获取URL请求参数
即获取URL中?
后面的参数
1 2 3 4 5 6
|
@app.route('/param') def param(): req_id = request.args.get('id') return str(req_id)
|
获取POST请求参数
1 2 3 4 5 6 7 8 9
|
@app.route('/upload', methods=['POST']) def upload(): f = request.files['pic'] with open("./demo.png", 'wb') as new_file: new_file.write(f.read()) return str(request.form)
|
响应模板
用flask.render_template
,估计用不着,先不学。
重定向响应
1 2 3 4
| from flask import redirect @app.route('/redirect') def redirect_func(): return redirect('http://www.xxx.com')
|
返回JSON响应
用jsonify返回可以自动设置响应头的格式。
1 2 3 4 5
| from flask import jsonify @app.route('/json') def json(): some_dict = {} return jsonify(some_dict)
|
自定义响应
页面函数返回一个元组(response, status, headers)
,如("返回文本", 404, {'id_cache': 'asdf31S#$13A'})
。
也可以使用make_response
方式:
1 2 3 4
| rsp = make_response('返回文本') rsp.headers['id_cache'] = "asdf31S#$13A" rsp.status = "404 not found" return rsp
|
Cookies
必须使用make_response
方式响应:
- 设置:
rsp.set_cookie('key', 'value', max_age=7200)
(age单位秒)
- 删除:
rsp.delete_cookie('key')
- 获取:
rsp.cookies.get('key')
Session
必须先设置SECRET_KEY
,导入flask.session
。
session可以当做字典使用:session['username'] = 'alex'
,session.get('username')
异常处理
正常向用户抛出异常
需要导入flask.abort
,使用方法:abort(状态码)
。
程序错误捕捉
使用@app.errorhandler
。
1 2 3 4 5 6 7 8 9
|
@app.errorhandler(500) def internal_server_error(e): return "服务器搬家了"
@app.errorhandler(ZeroDivisionError) def zero_error(e): return "0不能做除数"
|
Flask 蓝图
1 2 3 4 5 6 7 8 9
| user_blueprint = Blueprint('user', __name__)
@user_blueprint.route("/test1", methods=["GET", "POST"]) def func(): pass
app.register_blueprint(user_blueprint)
|
Flask current_app
在别的地方假如要获取某个app实例的属性(比如redis或者mysql的相关信息在app的配置中,需要在其他文件中获取),不需要导入main.py,只需要导入flask.current_app
。
假如有多个app实例,那在函数中也用flask.current_app
。
Flask g对象
g对象是程序全局的一个临时变量,需要导入flask.g
。就是给了你一个类似request的变量,在本次请求内各个函数都可以用。(为啥不直接传参?)
Flask 钩子
@app.before_request
:每次请求都会执行的函数,无参数,不需要返回值!否则会直接作为返回值而不管页面返回。
@app.before_first_request
:在第一次请求之前执行的函数,无参数,不需要返回值。
@app.after_request
:每次请求结束后运行,有一个参数用来接收response_class,一般返回这个response。
@app.teardown_request
:每次请求结束后运行,比after_request更后,需要一个参数来接收异常(没有则为None)。假如前面有未经处理的异常,就不会调用after_request,但是仍然会调用这个。一般用来释放数据库连接。
graph LR
A[before_first_request] --> B[before_request]
B --> C[page]
C --> D[after_request]
D --> E[teardown_request]
C -.-> E
一个判断登陆实例
1 2 3 4 5 6 7 8 9 10 11 12
| def login_required(func): def wrapper(*args, **kwargs): if g.user_id is None: abort(401) else: return func(*args, **kwargs) return wrapper
@app.route("/profile") @login_required def profile(): return "hello world."
|
Flask RESTful
是flask的一个扩展库:pip install flask-restful
。
下面先来一个实例:
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
| from flask import Flask, jsonify from flask_restful import Api, Resource, reqparse
USERS = [ {"name": "zhangsan"}, {"name": "lisi"}, {"name": "wangwu"}, {"name": "zhaoliu"} ]
class Users(Resource): def get(self): return jsonify(USERS) def post(self): args = reqparse.RequestParser() args.add_argument('name', type=str, location='json', required=True, help="名字不能为空") args.parse_args() if args['name'] not in USERS: USERS.append({"name": args['name']}) return jsonify(USERS) def delete(self): USERS = [] return jsonify(USERS)
app = Flask(__name__) api = Api(app, default_mediatype="application/json")
api.add_resource(Users, '/users')
app.run(host='0.0.0.0', port=5001, use_reloader=True)
|
稍微修改一下,让GET方法能获取到某个单个用户的信息:
1 2 3
| def get(self, userid): return jsonify({ 'name': USERS[int(userid)].get("name") }) api.add_resource(UserId, '/user/<userid>')
|