127

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

4

6 回答 6

91

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

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

在理想世界中,这将是 的唯一特征Flask-SQLAlchemy,但实际上,它增加了一些东西。查看文档以获取更多信息。或者查看这篇博客文章以及它们的概述:Demystifying Flask-SQLAlchemy(更新:原始文章目前不可用,webarchive 上有一个快照)。

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

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

于 2016-11-13T20:27:50.980 回答
25

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

使用 Flask-SQLAlchemy 的积极方面


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

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

使用 Flask-SQLAlchemy 的负面影响


  1. 如果你需要的话,使用 Flask-SQLAlchemy 会给从 Flask 迁移到 Pyramid 增加额外的困难。这主要是由于 Flask_SQLAchemy 上的自定义声明性基础模型。
  2. 使用 Flask-SQLAlchemy,你可能会使用一个社区比 SQLAlchemy 本身小得多的包,我不能轻易地在短期内放弃积极的开发。
  3. 如果您不知道 Flask-SQLAlchemy 的一些不错的附加功能,它们可能会让您感到困惑。
于 2016-11-13T21:37:17.133 回答
22

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

于 2013-03-04T03:18:24.280 回答
20

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

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

您可以在会话常见问题解答的第二个问题中找到此引用和详细动机。

于 2013-01-16T07:48:39.183 回答
9

正如@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 定义的模型。

于 2014-01-06T20:46:09.793 回答
3

下面是一个例子,说明 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),您可能会对对象保存到数据库的方式(如表的名称)做出不同的假设,因此您必须编写自己的适配器类。

于 2015-07-08T16:48:31.590 回答