SQLAlchemy: "session"由谁负责?(以及如何进行单元测试)

2 投票
1 回答
899 浏览
提问于 2025-04-15 21:26

我需要一些关于如何使用 session 对象和 SQLAlchemy 的指导,以及如何组织我映射对象的单元测试。

我希望能做到的事情大概是这样的:

thing = BigThing() # mapped object
child = thing.new_child() # create and return a related object
thing.save() # will also save the child object

为了实现这个目标,我在想是不是可以让 BigThing 自己把自己(以及它的子对象)添加到数据库里——不过这样做是不是不太好呢?

尽早添加对象的一个原因是数据库会自动分配 id 值——越早可用,问题就越少(对吧?)

管理 session 对象的最佳方法是什么?
谁来负责 session
它应该在需要的时候才创建,还是可以长时间保存?

关于我映射对象的单元测试呢?……session 应该怎么处理?
让映射对象自动添加自己到数据库里可以吗?这样做会不会引发问题?

1 个回答

2

会话就像一个用来存放物品的盒子。你当然可以写一个 __init__ 方法来自动把物品放进去,但这就意味着只有一个全局的(唯一的)会话。这样在很多情况下会出现问题,但同时也能让写代码变得简单一些。这就是显式和隐式的选择。有些人遵循Python的哲学,有些人则不在意。我更喜欢明确指定一个盒子来存放物品。

需要注意的是,只要对象已经通过关系和会话关联,就不需要明确地将子对象添加到会话中。这就是 级联规则 的作用。默认的 'save-update' 就能做到你想要的。你可能还会对 'all, delete-orphan' 感兴趣,这样可以实现“私有”对象,意味着这些对象应该和它们的父对象一起被删除。

我觉得实现 save() 方法有一些问题。在当前版本的SQLAlchemy中,没有办法直接说“保存这些对象”。之前是有这样的功能,但从来不可靠。Session.flush()(它是从 Session.commit() 调用的)会把所有的更改都刷新到数据库。这可能是SQLAlchemy最让人烦恼的特性之一,导致我在某些项目中无法使用它。

单元测试非常简单(至少当你明确指定会话时),可以查看其他问题中的示例代码

撰写回答