Flask的基本原理与核心知识
环境安装
1 2 3 4 5 6 7 8 9 10 11 12 |
# 多个 Python 版本时安装为指定版本安装 pip curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py python get-pip.py python3.6 get-pip.py pip install pipenv pipenv install # 安装虚拟环境 pipenv shell # 启动虚拟环境 pipenv install flask ... pipenv uninstall flask ... pipenv graph # 打印出所有信息 exit # 退出环境 |
https://github.com/pypa/pipenv
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# app.run 参数 app.run(debug=True) # 打开调试模式 host='0.0.0.0' # 设置主机 IP port=5000 # 设置端口 # 路由注册方法 # 1.装饰器 @app.route("/hello") # 2.add_url_rule app.add_url_rule('/hello', view_func=hello) # 导入配置文件(假定为同级 config.py 文件) app.config.from_object('config') app.config['XXX'] # 读取,要求 XXX 全部为大写 |
蓝图
解决分割视图函数后循环导入的问题:
- 实例化核心对象 app -> 插入blueprint
- blueprint -> 插入视图函数、还可包含静态文件夹和模板文件夹
蓝图放在每个包的__init__.py 中进行注册,然后各文件进行导入
1 2 3 4 5 |
from flask import Blueprint package_name = Blueprint('package_name', __package__) from web.package_name import xxx |
然后在 主 app 目录下的__init__.py 上进行注册:
1 2 3 4 5 6 7 8 9 10 11 12 |
from flask import Flask def create_app(): app = Flask(__name__) app.config.from_object('config') register_blueprint(app) return app def register_blueprint(app): from app.package_name import package_name app.register_blueprint(package_name) |
参数验证:wtforms
模型:flask-sqlalchemy
Flask 经典错误:RuntimeError: Working outside of application context.
4个核心对象:Flask和AppContext应用上下文、Request和RequestContext请求上下文
这一问题通常出现在单元测试和离线应用中,因为视图函数的请求中 Flask 会替你处理上下文的问题,出现的原因为current_app指向栈顶元素,而由于栈顶为空无法获取到上下文,解决方法是获取应用上下文并压入栈
自己推入应用上下文的主要应用场景为离线应用和单元测试
1 2 3 4 5 6 7 8 |
ctx = app.app_context() # 得到应用上下文 ctx.push() # 入栈 ... ctx.pop() # 更简洁的写法 with app.app_context(): ... |
Ctrl/Cmd+Alt/Option+左/右方向键返回上下层或进入下一层源代码
SQLAlchemy中解决 app上下文的问题:
RuntimeError: No application found. Either work inside a view function or push an application context.
1 2 3 4 5 6 7 8 9 10 11 |
# 方法一 db.init_app(app) db.create_all(app=app) # 传入 app # 方法二 db.init_app(app) with app.app_context(): db.create_all() # 方法三(初始化时传入) db = SQLAlchemy(app=app) |
线程
多线程可以充分的利用 CPU 的性能优势,Python GIL 全局解释器锁,对于 CPU 密集型程序多线程鸡肋,对于 IO 密集型程序 Python 的多线程则有意义
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import threading def worker(): print('I am thread') t = threading.current_thread() print(t.getName()) t = threading.current_thread() print(t.getName()) # 主线程MainThread new_t = threading.Thread(target=worker, name='my_thread') # 这个子线程的默认名称为Thread-1,可通过 name 来指定名称 new_t.start() # 启动线程 |
Flask 使用 Werkzeug 的 Local 和 LocalStack来实现线程隔离
1 |
from werkzeug.local import Local, LocalStack |
对象序列化
1 2 3 4 |
# 普通的直接使用 jsonify(obj.__dict__) # 但对于对象中还包含对象甚至多层嵌套的: json.dumps(obj, default=lambda o:o.__dict__) |
Jinja2
1 2 3 4 5 6 7 8 9 10 11 |
# url_for <link rel="stylesheet" href="{{ url_for('static', filename='xxx.css') }}"> # flash('Test message') {% set messages = get_flashed_messages() %} # 限定作用域 {% with messages = get_flashed_messages() %} {{ messages }} {% endwith %} |
数据库
1 2 3 4 |
pip3 install Flask-Migrate # migrate = Migrate(app, db) flask db init flask db migrate |