python - 在 flask 中正确使用 sqlalchemy

标签 python flask sqlalchemy

我正在为 flask 和 sqlalchemy 制作一个基本的 API。我在 sqlalchemy 文档中读到,您应该只拥有一个带有连接字符串的引擎。这应该如何在 app> __init__.py 文件中构建?在运行以启动 flask 服务器的 flask 文件中?这是我的 github 存储库,因为我认为只查看当前的应用程序结构和它可能存在的任何缺陷会更容易。 https://github.com/JayHelton/Geekdom_Web_App

在我的查询方法中,我每次都在创建一个新的数据库引擎,它似乎可以正常工作,但我不想在多人尝试调用这些方法时遇到问题。谢谢你!

最佳答案

当然已经有一个 Flask 扩展 Flask-SQLAlchemy - 在 Flask 文档 SQLAlchemy in Flask 中也提到了。但与大多数 Flask 扩展一样,它所做的只是将 Flask 和 SQLAlchemy(或任何其他库)“连接”在一起。最好的文档往往是源代码 :)

github.com/mitsuhiko/flask-sqlalchemy/blob/master/flask_sqlalchemy/__init__.py

然而,在 Flask-SQLAlchemy 的情况下,它有很多代码,还有一些关于作用域 session 与 Flask 上下文、修改跟踪和持续时间调试交织在一起的黑魔法,以及一些在 Web 应用程序中有用的东西以及所有可能的极端情况和一些其他事物。我会说它有点过度设计。我不是说您不应该使用它 - 只是从扩展代码中乍一看,SQLAlchemy 和 Flask 之间的连接是不可见的,因此可能需要更多阅读时间。

但是如果你想自己做它很容易(好吧,就像 SQLAlchemy 一样容易) - 只需初始化 SQLAlchemy 就可以得到一个 sessionmaker,并且然后在每个请求之前创建一个 session ,然后不要忘记在请求之后关闭它 :) 并在你的 Flask 处理程序中使用这个 session (我的意思是 @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) 是最佳实践。

最重要的是在各个请求之间建立隔离 session - 在我的解决方案中, session 是在 before_request Hook 中为每个请求创建的。 Flask docs "SQLAlchemy in Flask" 的解决方案使用 scoped_session,它具有基本相同的效果(使用线程局部变量实现,每个线程有一个单独的 session )。

广告应用程序架构:对于更大的应用程序,最好使用 Larger Applications patternsblueprints 。所以我所有的 Flask 路由处理程序都将在蓝图中,然后我将有一个“主要”函数 get_app() 1) 创建 Flask 对象 2) 用它注册蓝图 3) 创建 SQLAlchemy 引擎和将 Session() 与 Flask app.before_request Hook 。大致类似于 thisthis


you should only ever have one engine

为什么?从技术上讲,引擎只是一个到数据库的连接(池)。如果您的应用程序使用三个独立的数据库怎么办?那么你当然需要三个引擎。

当然,一个 session 只连接到一个引擎。所以你需要多个 session 。以及模型类的多个声明性基础,而且 - 最重要的是 - 不要意外混淆。这就是为什么建议只使用一个引擎 - 如果可能的话。

您可以根据请求创建引擎 - 这在技术上是正确的,但效率低下。为整个应用程序保留一个引擎,只为每个请求创建 session 。

关于python - 在 flask 中正确使用 sqlalchemy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43459182/

相关文章:

python - SQLAlchemy:使用函数确定查询返回的结果

python - 如何保持时间戳的毫秒分量,即使它的值为零?

python - 如何在 PyCharm 中用作 jupyter 笔记本的 python 文件中嵌入 Markdown

python - 在 python-wordpress-xmlrpc 请求上设置自定义 header

javascript - 在 Flask 中将客户端数据传输到服务器端

python - SQLAlchemy 批量插入空列

python - 无法下载网页的完整源代码

python - 向现有 SQLAlchemy 表添加外键约束

python - flask 管理员 : How to make a query according to the current user's id and role?

python - sqlalchemy:在同一文件中创建两个数据库