烧瓶-sqlalchemy 或 sqlalchemy

Posted

技术标签:

【中文标题】烧瓶-sqlalchemy 或 sqlalchemy【英文标题】:flask-sqlalchemy or sqlalchemy 【发布时间】:2012-12-29 21:44:42 【问题描述】:

我是烧瓶和 sqlalchemy 的新手,我刚开始开发烧瓶应用程序,我现在正在使用 sqlalchemy。我想知道使用 flask-sqlalchemy 与 sqlalchemy 是否有任何显着的好处。我在http://packages.python.org/Flask-SQLAlchemy/index.html 中找不到足够的动机,或者我可能不明白其中的价值!!非常感谢您的澄清。

【问题讨论】:

嗯,这里还是没有满意的答案。谁能解释一下 flask-sqlalchemy 在 Flask 应用程序中的实际具体好处是什么? 一个很大的缺点是,Flask-SqlAlchemy 没有提供任何在应用程序中设置多租户的方法。这是 IMO 最大的负面影响。 binds 提供的只是将不同的数据库附加到不同的模型,而无法使用相同模型的租户特定数据库。 @RohitJain 你帮我省了很多麻烦。我也有同样的问题。我认为 Flask-SQLAlchemy 的好处在于,如果您正在使用模型等构建数据库。我发现 SQLAlchemy 文档读起来很难,但非常强大和灵活。 towardsdatascience.com/… 解释了 flask-sqlalchemy 的一些缺点,即当您想要跨烧瓶和非烧瓶上下文(例如某些数据管道)共享数据模型时。它建议使用 sqlalchemy,还建议使用 sqlalchemy 的 scoped_session 解决flask-sqlalchemy 解决的线程问题 【参考方案1】:

Flask-SQLAlchemy 的主要功能是与 Flask 应用程序的适当集成 - 它创建和配置引擎、连接和会话,并将其配置为与 Flask 应用程序一起使用。

此设置非常复杂,因为我们需要创建 scoped session 并根据 Flask 应用程序请求/响应生命周期正确处理它。

在理想的世界中,这将是Flask-SQLAlchemy 的唯一功能,但实际上,它增加了一些东西。查看the docs 了解更多信息。或者看这篇博文,里面有它们的概述:Demystifying Flask-SQLAlchemy(更新:原文章暂时没有,有一个snapshot on webarchive)。

当我第一次使用 Flask 和 SQLAlchemy 时,我不喜欢这种开销。我过去并从扩展中提取了会话管理代码。这种方法很有效,尽管我发现要正确地进行这种集成非常困难。

因此,更简单的方法(在我正在处理的另一个项目中使用)是将Flask-SQLAlchemy 放入其中并且不使用它提供的任何附加功能。您将拥有db.session,并且可以像使用纯SQLAlchemy 设置一样使用它。

【讨论】:

我还是一头雾水。链接的博客文章(和官方文档!)列出了一些普通的 SQLAlchemy 特性(如声明性基础),就好像它们是 Flask-SQLAlchemy 特性一样;目前尚不清楚他们是否将 SQLAlchemy 内置的东西归功于他们,或者他们已经重新实现了它(如果是后者,也不清楚他们这样做的原因)。您的第一段列出了两个功能:用于会话管理的便利包装器(但如果您想在 outside Flask 使用您的 SQLAlchemy 模型,您是否不需要滚动自己的包装器?)和一些未指定的“配置” “使用 Flask 应用程序”。这是什么意思 我也被一些问题弄糊涂了。链接的博客文章非常清楚 IMO,例如,它说“支持查询属性和分页的自定义声明性基本模型”,关键是“自定义”,“支持查询属性和分页”是它添加的内容SQLAlchemy 的声明性基础。 关于“便利包装” - 它们不是为了方便,而是为了让事情正常工作。要开始使用 SQLAlchemy,您需要数据库连接(eninge / connection / session)对象,并且您不想在每次需要进行 SQL 查询时都创建这些对象,因此应该全局创建这些对象,并且可以在应用程序代码中使用这些对象。因此,您可以执行“from yourapplication import db”之类的操作,然后执行“db.session.something()”,而无需考虑如何正确创建和初始化此“db”对象。 关于未指定的“配置”到“使用 Flask 应用程序” - 它实际上在第二段中指定:This setup is quite complex as we need to create the scoped session and properly handle it according to the Flask application request/response life-cycle. 在 SQLAlchemy 文档中查看更多详细信息:When do I construct a Session, when do I commit it, and when do I close it? 和 @987654326 @. 感谢您的链接:web.archive.org/web/20190901011222/http://derrickgilland.com/…。对这个问题以及如何解决这个问题有很好的解释。【参考方案2】:

Flask-SQLAlchemy 为您提供了许多不错的额外功能,否则您最终会使用 SQLAlchemy 自行实现。

使用 Flask-SQLAlchemy 的积极方面


    Flask_SQLAlchemy 为您处理会话配置、设置和拆卸。 为您提供使查询和分页更容易的声明性基本模型 后端特定设置。Flask-SQLAlchemy 扫描已安装的库以获取 Unicode 支持,如果失败则自动使用 SQLAlchemy Unicode。 有一个名为 apply_driver_hacks 的方法可以自动将健全的默认值设置为 mysql 池大小等设置 有很好的内置方法 create_all() 和 drop_all() 用于创建和删除所有表。如果你做了一些愚蠢的事情,对测试和 python 命令行很有用 它为您提供 get_or_404() 而不是 get() 和 find_or_404() 而不是 find() 代码示例位于 > http://flask-sqlalchemy.pocoo.org/2.1/queries/

自动设置表名。 Flask-SQLAlchemy 自动设置你的表名转换你的 ClassName > class_name 这可以通过设置 __tablename__ 类来覆盖 列表项

使用 Flask-SQLAlchemy 的负面影响


    使用 Flask-SQLAlchemy 会给 for 如果需要的话,可以从 Flask 迁移到 Pyramid。这主要是由于 Flask_SQLAchemy 上的自定义声明性基础模型。 使用 Flask-SQLAlchemy 时,您会冒着使用社区比 SQLAlchemy 本身小得多的包的风险,我不能轻易放弃积极的开发。 如果您不知道 Flask-SQLAlchemy 的一些不错的附加功能,可能会让您感到困惑。

【讨论】:

【参考方案3】:

说实话,我没有看到任何好处。恕我直言,Flask-SQLAlchemy 创建了一个您并不真正需要的附加层。在我们的例子中,我们有一个相当复杂的 Flask 应用程序,它具有多个数据库/连接(主从),同时使用 ORM 和 Core,其中除其他外,我们需要控制我们的会话/数据库事务(例如,dryrun 与提交模式)。 Flask-SQLAlchemy 添加了一些额外的功能,例如自动销毁会话,为您假设一些通常不是您需要的东西。

【讨论】:

是的,在您的用例中,Flask-SQLAlchemy 似乎已过时。但是,如果 OP 有这样的情况,他可能不会问这个问题。对于对会话范围一无所知的新用户,Flask-SQLAlchemy 绝对是必须的!【参考方案4】:

SQLAlchemy 文档明确指出您应该使用 Flask-SQLAlchemy(尤其是如果您不了解它的好处!):

[...] Flask-SQLAlchemy 等产品 [...] SQLAlchemy 强烈建议在可用时使用这些产品。

您可以在Session FAQ 的第二个问题中找到这句话和详细的动机。

【讨论】:

Flask-sqlalchemy 似乎没有维护。最后一次更新是在 2013 年 8 月 1 日。这个建议还有意义吗? @pmav99 只要您没有具体问题,我仍然会推荐它,尤其是对于新用户。 似乎在 2014 年 11 月得到积极维护。许多最近的提交。 github.com/mitsuhiko/flask-sqlalchemy/commits/master 即使 OP 没有直接询问,imo。他想知道 Flask-SQLAlchemy 的好处。您的回答实际上是“即使您不知道有什么好处也可以使用它”——是的,有什么好处? 这个答案没有回答 OP 的问题。您推荐的是 flask-sqlalchemy,但没有提供很多推荐背后的理由。【参考方案5】:

正如@schlamar 建议的那样,Flask-SqlAlchemy 是一件好事。我只是想为那里提出的观点添加一些额外的上下文。

不要觉得你在选择一个而不是另一个。例如,假设我们想使用使用 Flask-Sqlalchemy 的模型从表中获取所有记录。就这么简单

Model.query.all()

对于很多简单的情况,Flask-Sqlalchemy 完全没问题。我想补充的一点是,如果 Flask-Sqlalchemy 不能做你想做的事,那么你没有理由不能直接使用 SqlAlchemy。

from myapp.database import db

num_foo = db.session.query(func.count(OtherModel.id)).filter(is_deleted=False).as_scalar()

db.session.query(Model.id, num_foo.label('num_foo')).order_by('num_foo').all()

如您所见,我们可以轻松地从一个跳转到另一个,而在第二个示例中,我们实际上使用的是 Flask-Sqlalchemy 定义的模型。

【讨论】:

"例如,假设我们想使用 Flask-Sqlalchemy 的模型从表中获取所有记录。就像Model.query.all() 一样简单" -- 这一切都可以通过 来完成 SQLAlchemy,使用 Flask-SQLAlchemy 在这里绝对没有什么新东西。 你太棒了!我偶然发现了这篇文章,它解决了我遇到的一个问题。安装 anaconda 后,由于某种原因,正常更新无法正常工作。从 Model.query.all() 更改为 db.session.query(Model).all() 出于某种原因允许会话正常跟踪和更新。【参考方案6】:

这是一个例子,说明 flask-sqlalchemy 比普通 sqlalchemy 带来的好处。

假设您使用的是 flask_user。

flask_user 自动创建和验证用户对象,因此它需要访问您的数据库。 UserManager 类通过调用一个称为“适配器”的东西来完成此操作,该适配器抽象了数据库调用。您在 UserManager 构造函数中提供了一个适配器,并且该适配器必须实现这些功能:

class MyAdapter(DBAdapter):
    def get_object(self, ObjectClass, id):
        """ Retrieve one object specified by the primary key 'pk' """
        pass

    def find_all_objects(self, ObjectClass, **kwargs):
         """ Retrieve all objects matching the case sensitive filters in 'kwargs'. """
        pass


    def find_first_object(self, ObjectClass, **kwargs):
        """ Retrieve the first object matching the case sensitive filters in 'kwargs'. """
        pass

    def ifind_first_object(self, ObjectClass, **kwargs):
        """ Retrieve the first object matching the case insensitive filters in 'kwargs'. """
        pass

    def add_object(self, ObjectClass, **kwargs):
        """ Add an object of class 'ObjectClass' with fields and values specified in '**kwargs'. """
        pass

    def update_object(self, object, **kwargs):
        """ Update object 'object' with the fields and values specified in '**kwargs'. """
        pass

    def delete_object(self, object):
        """ Delete object 'object'. """
        pass

    def commit(self):
        pass

如果您使用的是 flask-sqlalchemy,您可以使用内置的 SQLAlchemyAdapter。如果您使用的是 sqlalchemy (not-flask-sqlalchemy),您可能会对对象保存到数据库的方式(如表的名称)做出不同的假设,因此您必须编写自己的适配器类。

【讨论】:

以上是关于烧瓶-sqlalchemy 或 sqlalchemy的主要内容,如果未能解决你的问题,请参考以下文章

Flask 进阶系列:SQLAlchemy 扩展学习

无法导入名称'日期时间'python烧瓶sqlalchemy

SQLAlchemy 烧瓶删除

在烧瓶中使用 SqlAlchemy 模型

SQLAlchemy 合并()不使用烧瓶工作

用于生产和开发的烧瓶 postgresql sqlalchemy 配置