能否在SQLAlchemy会话中添加对象而不使用session.add()?

6 投票
2 回答
6559 浏览
提问于 2025-04-16 06:41

我有一些类,它们和数据库表通过SQLAlchemy连接(如果这点重要的话,是非声明式的)。因为我希望这个应用程序能够进行单元测试,所以所有和SQLAlchemy会话的交互都集中在一个类里。使用这个应用程序的流程大致是这样的:

m = Model("mysql://localhost/mydb")
s1 = Service("somename")
m.session.add(s1)
s1 is m.get_service("somename") # True

其实这个流程比这更简化,但先这样理解吧。

有没有办法跳过session.add()这一步?换句话说,如果我创建了一个映射的类实例,是否可以让它自动加入到当前的SQLAlchemy会话中(如果有的话)?

2 个回答

3

其实,并不是每次都这样。如果你已经定义了子模型和父模型之间的关系,或者是多对多的关系,你只需要明确地使用 .add 来添加父对象。子对象在被指定父对象的时候会自动添加,因为这些父对象通常已经在数据库或者会话中存在了。举个例子:

a1 = Author(name='Pynchon') # out of session
session.add(a1) # in session
b1 = Book(name='Gravity`s Rainbow') # out of session
b1.author = a1 #in session
a2 = session.query(Author).filter(name='Eco').one() # in session
b2 = Book(name='Baudolino') # out of session
b2.author = a2 # in session

当然,你需要事先指定好映射器之间的 'author' 关系。

6

在SQLAlchemy中,你只能通过将表的元数据绑定到一个引擎来实现这个功能。这种方法在SQLAlchemy的ORM部分是行不通的。

http://www.sqlalchemy.org/docs/core/schema.html?highlight=metadata#binding-metadata-to-an-engine-or-connection

一种解决这个问题的方法是使用一个可以在任何地方访问的作用域会话。

http://www.sqlalchemy.org/docs/orm/session.html?highlight=scoped%20session#sqlalchemy.orm.scoped_session

撰写回答