当然,已经有一个Flask扩展 Flask-SQLAlchemy - 也在Flask文档 SQLAlchemy in Flask中提到。但像大多数Flask扩展一样,它所做的只是将Flask和SQLAlchemy(或任何其他库)“连接”起来。最好的文档通常是源代码 :)
github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py
然而,对于Flask-SQLAlchemy来说,它包含了大量的代码和一些关于作用域会话、Flask上下文、修改跟踪和持续调试以及在Web应用程序中非常有用的内容以及所有可能的角落和边角情况和其他一些东西的黑魔法。我认为这有点过度设计。我并不是说你不应该使用它 - 只是SQLAlchemy和Flask之间的连接在扩展代码中并不明显,因此可能需要更多的阅读时间。@app.route
函数)中使用这个会话即可。import flask
import sqlalchemy
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class Item (Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
title = Column(String)
engine = sqlalchemy.create_engine('sqlite:///bestappever.db', echo=True)
Session = sessionmaker(bind=engine)
# create all tables if you wish...
Base.metadata.create_all(engine)
app = flask.Flask(__name__)
@app.before_request
def create_session():
flask.g.session = Session()
@app.teardown_appcontext
def shutdown_session(response_or_exc):
flask.g.session.commit()
flask.g.session.remove()
@app.route('/')
# just use the SQLAlchemy session :)
items = flask.g.session.query(Item).all()
return flask.render_template('index.html', items=items)
请查看我的示例Flask + SQLAlchemy应用程序: https://github.com/messa/db-workshop-web-app/blob/sqlalchemy/anketa.py
正如您所见,您甚至可以将所有内容放在一个大文件中,但将其拆分为多个文件(其中一个通常命名为model.py
)是最佳实践。
最重要的是在各个请求之间具有隔离的会话 - 在我的解决方案中,会话是在before_request
钩子中为每个请求创建的。Flask文档中"SQLAlchemy in Flask"的解决方案使用scoped_session
,它基本上具有相同的效果(使用线程本地变量实现每个线程的单独会话)。
广告应用程序架构:对于更大的应用程序,最好使用更大的应用程序模式和蓝图。所以我的所有flask路由处理程序都将在蓝图中,然后我会有一个"main"函数get_app()
,它会 1)创建Flask对象 2)向其注册蓝图 3)创建SQLAlchemy引擎并将Session()
钩子与Flask app.before_request
连接起来。大致类似于这个或这个。
你应该只有一个引擎
为什么?从技术上讲,引擎只是连接到数据库的连接池。如果您的应用程序使用三个单独的数据库呢?那么您当然需要三个引擎。
但是,会话当然连接到恰好一个引擎。因此,您需要多个会话。以及多个声明性基础模型类,并且最重要的是不要意外混淆它们。这就是为什么建议只有一个引擎 - 如果可能的话。
您可以根据请求创建引擎 - 这在技术上是正确的,但效率低下。保持整个应用程序的一个引擎,只需每个请求创建一个会话。