【问题标题】:Mixing SQLAlchemy and Django in Python code base and maintain transaction integrity在 Python 代码库中混合 SQLAlchemy 和 Django 并维护事务完整性
【发布时间】:2014-12-09 13:22:14
【问题描述】:

我有一个项目,我想(需要?)在同一个 Web 代码库中混合 SQLAlchemy 模型、Django 模型和各自的 ORM。我希望默认有原子请求,并将 SQLAlchemy 事务生命周期与 Django 请求和 Django 事务管理器联系起来。

是否存在现有技术如何使 SQLAlchemy 使用 Django/连接和事务机制,反之亦然?

这种集成工作的良好起点是什么?有什么限制,例如如果您尝试重用相同的数据库连接?

缩小问题范围:

  • Django ORM 和 SQLAlchemy ORM 不会触及相同的表

  • 在第一步,我只关心当 HTTP 请求结束时,两个事务管理器以某种连贯的方式提交,例如如果 Django 提交事务,SQLAlchemy 也会这样做

  • 我如何说 SQLAlchemy 使用为 Django 配置的数据库连接?

  • 我可以将 SQLAlchemy 会话绑定到 Django 事务管理器吗?当 Django 打开数据库连接时,我可以打开一个新的 SQLAlchemy 会话并将其绑定到打开的 Django 事务吗?当 Django 提交时,我可以向 SQLAlchemy 发出信号以刷新其内容,以便它遵循相同的 cmmit。 Django 1.6 为原子事务引入了新语义,因此这可能会有所帮助。

【问题讨论】:

    标签: django sqlalchemy pyramid


    【解决方案1】:

    这真的不容易。我想知道这种努力是否值得。 SQLAlchemy 和 Django 使用非常不同的抽象和模式来处理对象持久性和事务。

    Django ORM 遵循Active Record 模式,其中对象更直接地映射到数据库表并封装所有访问和逻辑。当您调用 `save()' 方法时,对象中的更改直接转换为 SQL 代码更改的行。您可以自己管理事务,但基本上一切都只是处理底层数据库的语法糖。

    SQLAlchemy 遵循Data Mapper 模式,其中有另一层抽象负责在活动对象和数据库之间移动数据,彼此独立。对象甚至不知道存在数据库,对象和数据库表之间的映射非常非常灵活。此外,SQLAlchemy 在 Python 端还有另一个事务层,遵循Unit of Work 模式,它基本上将整个 SQL 事务封装为一个原子实体。通过主键在会话中跟踪对象,并以正确的顺序自动保存更改。

    来自 Django,我第一次使用 Flask 和 SQLAlchemy 时犯了很多人都会犯的错误,那就是试图模仿 Django ORM 在 SQLAlchemy 上的使用模式。例如,当您习惯了 Django-ORM 时,创建提交事务的 save() 方法看起来很明显,但在 SQLAlchemy 中这是一个糟糕的想法。我很难理解它们是如何混合得不好的。

    SQLAlchemy 声明性基方法封装了类-映射器-表关系,使其看起来更像 ActiveRecord 模式,但这可能会产生很大的误导,因为您开始认为对象本身具有数据库的知识。

    如果你真的需要这样做,考虑到 SQLAlchemy 语义如何更干净地映射到数据库,我认为最好的办法是将 SQLAlchemy 本身视为一个数据库,并创建一个知道如何将 Django 模型和查询映射到SQLAlchemy 模型映射器表。也许您甚至可以将 Django 模型本身与 SQLAlchemy 映射表一起使用。

    因此,例如,当您在 Django 中运行 save() 方法时,它应该从当前会话中检索和更改等效的 SQLAlchemy 对象,而不是在数据库上生成和运行 SQL,因此任何处理该对象的人都可以在SQLAlchemy 层将所有内容视为数据库。当你在 Django 中提交事务时,你就提交了 SQLAlchemy 会话。

    这可能是一个有趣的练习,但对于现实世界的用例,我真的认为这样做没有多大意义。

    更新答案

    看起来你想要的只是将 Django 事务与 SQLAlchemy 会话同步。您不需要为此共享连接实例。您可以使用 django-transaction-hooks 之类的东西来触发负责提交 SQLAlchemy 会话的回调。如果需要做相反的事情,在提交 SQLAlchemy 会话时提交 Django 事务,可以使用after_commit 事件。

    请注意,两个引擎之间不会有原子性。如果 SQLAlchemy 提交中出现问题,则无法回滚 Django 提交,反之亦然。

    【讨论】:

    • 嗨!谢谢你非常全面的回答。但我的问题更多的是“如何让 SQLAlchemy 使用来自 Django 的数据库连接”和“如何让 SQLAlchemy 在 Django 事务结束时提交”。 Django 1.6 引入了新的原子语义,所以理论上一定是可能的(它是开源的,而且都是开源的)。我会稍微修改一下问题以使其更窄。
    • 如果我共享连接,我会获得交易完整性吗?有什么理由不共享连接吗?
    • 没有。您必须共享游标,其对事务完整性的影响将取决于数据库。可以做到,但我认为不会比我上面概述的方法更容易。不管您是否共享交易,您可能都必须这样做。
    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 2010-09-24
    • 1970-01-01
    相关资源
    最近更新 更多