写在最前
- 后台编辑器对代码块的支持并不友好, 因此代码块大部分以图片的形式展现, 最后可能会把代码放到 github 上, 链接会在最后给出
- 在篇文章的示例中,所有的 API 的返回都是 JSON
- 使用到的扩展 flask-login/ flask-sqlalchemy/ flask-migrate
- 第一次使用 flask 及其扩展,如文章中存在错误,请各位包涵,期待各位的指点
最简单的app
- 默认监听的是 " 127.0.0.1:5000", 若想调整, 可以在run的时候加入参数 host 和 port
> app.run(host='0.0.0.0', port=8080)
...
* Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
- 最后部署项目的时候会用到 gunicorn, 通过 --bind 参数来调整
第一个 Blueprint
Blueprint 是用来管理一组相似视图(理解为管理api)的方法, 例如
# 用户API Blueprint
/api/users
/api/users/<user_id>
# 组API Blueprint
/api/groups
/api/groups/<group_id>
index blueprint
app.py 调整为
app.py
重新运行app.run()后, 在浏览器中输入 http://localhost:5000, 会看到相应的输出
output
配置文件
- 加载配置文件的方式有几种,from_object/ from_envvar/ from_pyfile
- 其中, from_envvar 会加载环境变量中指定的文件, 格式与 from_pyfile 相同, 路径为相对(app.py)或者是绝对路径
- 我更倾向于使用 from_envvar/ from_pyfile 这种方式来加载配置文件,理由如下
- 项目开发,一般会分为 开发环境/ 测试环境/ 生产环境,会有不同的配置文件
- 由于配置文件中可能会存放数据库连接信息,密钥等敏感字段,因此,不建议将测试/ 生产环境的配置上传到代码服务器上
- 理想的方式是通过配置中心服务来管理,但是配置中心服务不一定会有
- 项目的开发及初期运维可能会是同一个人,因此,可以在配置测试/ 生产环境的服务器时,由开发人员将所需配置直接写在相应的服务器上,通过环境变量的方式指定其路径即可
- 在使用 supervisor 来管理项目进程时,可以通过配置 environment 来实现
- 最简单的配置文件
# config.py
DEBUG = True
# app.py
...
加载配置文件
app.config.from_envvar('APP_CONFIG_FILE')
# 添加环境变量
> export APP_CONFIG_FILE="/yourpath/config.py"
# 或者在 supervisor 的配置文件中声明
# environment=APP_CONFIG_FILE="/yourpath/config.py"
数据库
- 用到的扩展组件
- flask-sqlalchemy: 基于ORM 框架 SQLAlchemy
- flask-migrate: 管理数据模型,用于初始化,升级,降级等操作
- 增加 ext.py, 用于定义(声明)用到的扩展组件
ext.py
- 修改配置文件(使用 SQLite 来说明)
# config.py
...
SQLALCHEMY_DATABASE_URI = 'sqlite:///tutorial.db'
- 若是使用 MySQL, 需要在配置文件中加入 SQLALCHEMY_POOL_RECYCLE = 3600, 会自动收回无用的数据库连接, 如果不加这个配置, 连接会在 8 小时后断开, 要重启 app 才可以恢复(这是在第一次使用的时候碰到的问题, 由于服务器没有关闭, 第二天一早在使用时, 出现了连接断开的异常)
- 修改 app.py
...
from ext import db, migrate
...
db.init_app(app)
migrate.init_app(app, db)
- 增加数据模型
base.py
user.py
- 初始化 migrate, 创建文件夹 migrations, 运行命令 flask db init, 这个时候查看数据库, 是没有User 表的, 因为通过 app.py 所引用的包中, 并没有使用到 models.user.User, 这里, 有几种方式可以解决这个问题,
- 一是, 先写用到 models.user.User 的 Blueprint, 接着在 app.py 中注册这个 Blueprint 即可
- 二是, 临时在 app.py 中导入, 在完成之后, 再删除导入即可
- 三是, 通过另外的管理脚本, 考虑到在初始化数据库时可能会有其他的操作, 创建了 manage.py 这个文件
manage.py
manage.py
增加蓝图 users
- 添加查询所有用户的api /api/users
views/user.py
views/__init__.py
- 修改 app.py
# app.py
...
from views import index, user
...
app.register_blueprint(user.bp)
- 浏览器中输入 http://localhost:5000, 会看到返回结果如下
配置登录认证
- 修改 models.user.User, 继承 flask_login.UserMixin, 并重写方法 get_id
models.user.py
- 修改配置文件 config.py, 增加 SECRET_KEY = 'yoursecretkey', 不建议用过于简单的key, 官方推荐通过 os.urandom 来生成, 这里可能有一个地方需要注意, 当服务部署为多进程时(使用 gunicorn), 千万避免写成如下形式, SECRET_KEY = os.urandom(16), 由于每个进程都会生成一个随机数, 可能会导致需要用户重复登录, 这是个很愚蠢的错误, 由于我在开发时使用了 supervisor + gunicorn 来管理, 因此忘记了多进程的问题, 困惑了我好一会儿
- 修改 app.py
app.py
- unauthorized 方法: 在用户未登录时, 会调用此方法
- load_user_from_request 方法: 通过 Request 信息(header/ body/ ...)加载用户, 有一点需要注意, 当 session 中存在用户信息时(在 request cookie 中包含 session_id), 不会调用此方法
- load_user 方法: 获取当前登录用户的信息
增加蓝图 login
views/login.py
- 修改 app.py
...
from views import index, user, login
...
app.register_blueprint(login.bp)
- 修改 views/users.py
...
from flask_login import login_required
...
@bp.route('')
@login_required
def list_users(): ...
- 此时, 访问 http://localhost:5000/api/users, 会返回 401 错误
- 登录, 访问 /api/sign/in
- 之后, 再次访问 /api/users, 就正常了
- 注销, /api/sign/out, 之后, 访问 /api/users 时, 就会返回 401
- 测试一下不登录的情况下访问 /api/users, 之前的 load_user_from_request 方法中, 有一句 if request.args.get('hack'): return User.query.get(1), 只要在请求上加上 ?hack=1, 就可以看到正常的结果
未完待续
- 通过 supervisor/ gunicorn/ nginx 来部署项目
- gunicorn/ supervisor 的配置项
相关链接
- flask 文档: https://flask.palletsprojects.com/en/1.1.x/
- flask_login 文档: https://flask-login.readthedocs.io/en/latest/
- flask_migrate 文档: https://flask-migrate.readthedocs.io
- flask_sqlalchemy 文档: https://flask-sqlalchemy.palletsprojects.com/en/2.x/
- 项目 Github 链接: https://github.com/liuxuange/flask_tutorial
鸣谢
- 感谢在项目中帮助过我的人(抱歉, 不便透露真实姓名)
推荐阅读:快门速度
-
西装太正式?双排扣也能轻松优雅
相比简洁轻松的的单排扣(特别是现在常见的两扣、3-roll-2),双排扣西装在国内似乎不那么受待见。基本除了一票绅装爱好者和时髦精之外,平日街上是挺难看到穿着双...
2020-02-26 -
唇膏不只是用来擦嘴的,竟然有这么多的妙用
小身材大用处,唇膏的这些妙用你造吗?相信每个女孩的包里,都少不了一支润唇膏,有的小伙伴甚至有N支。有些可能只用几次就闲置了,还有些时间久了唇膏过期了也不能用了。...
2020-02-26 -
这些鞋子都是适合春天穿的,可以搭配牛仔裤和小
初春单鞋|百元内平价学生党仙女单鞋你不得不知道的仙女单鞋这些鞋子都是适合春天穿的 可以搭配牛仔裤和小裙子性价比也都挺高的 所以学生党上班族都可喜欢的朋友们可以帮...
2020-02-26 -
判断你的穿搭是“高级感”还是“俗气感”,看这
每个女人都爱买衣服爱打扮自己,但是花同样的钱呈现的效果可能大相径庭。当然这并非是因为外貌的原因,几乎所有女孩子都可以靠化妆变身气质小美女,但是有好衣品,看起来就...
2020-02-26