我有两个 Python 类Note
并Link
映射到 Postgresql 表。 Note
具有对 , 的外键引用Link
,同时Link
通过一段 JSON 文本指向节点。链接指向除Note
s 之外的其他东西,但这在这里无关紧要。
Note
+------+------------------+---------+
| ID | NAME | NOTE_ID |
+------+------------------+---------+
| 1 | Alice | 5 |
| 2 | Bob | 20 |
| 3 | Carla | 6 |
+------+------------------+---------+
Link
+------+--------------+
| ID | CONTENT |
+------+--------------+
| ... | ... |
| 5 | {"t":1} |
| 6 | {"t":3} |
| ... | ... |
| 20 | {"t":2} |
+------+--------------+
现在我想要的是每当我创建一个新的Note
note = Note('Danielle')
它会自动进入该行
(4, 'Danielle', 21)
进入Note
, 并进入
(21, '{"t":4}')
进入Link
. 到目前为止,这是我尝试过的:我创建了Note
对象,然后尝试Link
在@events.after_insert
事件中创建:
class Note(Entity):
name = Field(Unicode)
link = ManyToOne('Link')
. . .
@events.after_insert
def create_link(self):
"""
Create and persist the short link for this note. Must be done
in this after_insert event because the link table has a foreign
key that points back to the note. We need the note to be
already inserted so we can use its id.
"""
self.link = Link.build_link_for_note(self)
elixir.session.flush()
print("NOTE %s GOT LINK %s" % (self, self.link))
在我有的链接课程中
class Link(Entity):
. . .
@classmethod
def build_link_for_note(cls, note):
return Link(content='{"id": %d}' % note.id)
两个表都有自动递增的主键,所以不用担心。我使用此代码得到的错误是:
File ".../sqlalchemy/orm/session.py", line 1469, in flush
raise sa_exc.InvalidRequestError("Session is already flushing")
InvalidRequestError: Session is already flushing
我会买那个。在 Note 存储到数据库之后,该@after_insert
事件被调用(我认为) ,这发生在当前会话刷新期间。当然,如果我删除呼叫,那么它当然会打印elixir.session.flush()
NOTE <Note id:4 name:Danielle> GOT LINK <id:None content:{"t": 4}>
这又是有道理的,因为我无法保留链接!
所以我的问题是,我怎样才能在一个请求中同时创建一个注释和一个链接,以便相互依赖的 id 可用并正确记录?
PS我知道这里的模式有点不寻常,我可以通过(1)产生一个异步创建链接的任务或(2)让Link.content
方法懒惰地创建链接来解决这个问题。这些解决方案需要一些并发注意,所以我真的希望一个简单、直接的 SQLAlchemy 解决方案与一个会话可以工作。