扩展什么时候读配置?为什么 init_app 之后改配置有时生效、有时不生效?一个扩展对象能不能给多个应用用?这篇用 SQLAlchemy、Flask-Caching、Flask-Login 和两个自己写的小扩展逐项验证。
SQLAlchemy() 先不带 app 创建:此时还没有绑定任何应用 init_app 之前访问 db.engine → RuntimeError: Working outside of application context. init_app 之后,应用上下文里 db.engine = Engine 用别的(没有 init_app 的)应用的上下文访问 → RuntimeError: The current Flask app is not registered with this 'SQLAlchemy' instance. Did you forget to call 'init_app', or did you c app.extensions 里登记了: ['sqlalchemy']
上一篇:Application Factory;下一篇:Flask-Login 登录流程。
init_app 之后再把 URI 改成 other.db,引擎实际指向: sqlite:///%3Amemory%3A init_app 时没有配置 URI → RuntimeError: Either 'SQLALCHEMY_DATABASE_URI' or 'SQLALCHEMY_BINDS' must be set.
Flask-Caching:init_app 后把 CACHE_TYPE 改成 NullCache,cache.get 仍是 1 (用的是 init_app 时的 SimpleCache) Flask-Login:init_app 之后设置 login_view 仍然有效: late_login
同一个 db 对象,在 x、y 两个应用上下文里得到的引擎不同: True
先 init_app 再设配置 → RuntimeError: Either 'SQLALCHEMY_DATABASE_URI' or 'SQLALCHEMY_BINDS' must be set. 先设配置再 init_app → 成功
init_app 之后改配置:LazyExt.greet() = 改后(lazy) | EagerExt.greet() = hello EagerExt 对象被两个应用共用时(把值存在 self 上):g_ 的上下文里 greet() = g2 的值 (被第二次 init_app 覆盖了)
这一节是后面第 80 篇「自定义扩展」的铺垫。