以下是我的SQLAlchemy模型的最简单描述:
Host对象(Base的子类)和Network对象(也是Base)。主机与网络具有1:多的关系,并且与主机关联的网络对象可以直接与主机对象的信息一起识别,作为其启动的一部分。 (即主机的__init__()
提供了所有必要的信息,以便能够通过SQLAlchemy会话找到网络对象。
我正在考虑的是将sqlalchemy会话传递给Host对象,以便Host.__init__()
可以查询数据库并找到正确的Network对象,即
new_host = Host(sqlalchemy_sb_session, ip_address)
并直接在__init__()
中建立关联。这对我来说似乎非常难看,但我想不出任何其他方法让Host对象能够将自己与Network对象相关联。
我知道这会奏效,但必须有更好的方法。别人怎么解决这个问题?
答案 0 :(得分:3)
我会避免将Session
对象传递给类的构造函数
如果从主机中轻松找到网络,您真的需要保持数据库中的关系吗?您可以恰当地使用SA查找:
class Host(...):
...
@property
def Network(self):
Session.object_session(self).query(Network).find(*my_search_criteria*)
但显然,如果您拥有Network
对象,并且必须确保它们存在,则某些查询会更容易。在这种情况下,Session.object_session的技巧可以再次使用,但它不适用于尚未添加到会话的新创建的对象。
在这种情况下,您应该能够使用SessionExtension对象。使用结构应类似于以下内容:
from sqlalchemy.orm.interfaces import SessionExtension
class TestSessionExtension(SessionExtension):
def before_flush(self, session, flush_context, instances):
for obj in session.new:
if isinstance(obj, Host):
# if the Host has no Network object assigned, then...
# ... search-or-create the Network object using 'session'
# ... assign this network object to the Host
Session = sessionmaker(bind=engine, extension=TestSessionExtension())