我有一个看起来像这样的课程:
class Foo(Base):
pk = Column(Integer, Sequence('foo'), primary_key=True)
我想创建另一个字段ref
,对于新创建的对象,默认等于pk
。不幸的是,我使用的Postgres有一个non-standard nextval()
function,所以我不能简单地将两个列都默认为Sequence对象。
这是我目前的解决方案:
class Foo(Base):
pk = Column(Integer, Sequence('foo'), primary_key=True)
ref = Column(Integer, index=True, nullable=False, default=func.currval('foo'))
然而,这取决于两件事:SQLAlchemy在pk
之前生成带ref
的INSERT语句,和 Postgres从左到右评估表达式(所以{{1} } nextval()
生成的调用始终发生在pk
生成的currval
调用之前。
我非常感谢有关如何做得更好的任何建议!
编辑:还有更多设置ref
或其他内容并强制调用者更新default=-1
字段的解决方案。这对SQLA / Postgres语义的变化更安全,更健壮,但对于该类客户来说非常不方便。
答案 0 :(得分:2)
可以使用SQLAlchemy的ORM after_insert
映射器事件:
from sqlalchemy import event
# Model from OP
class Foo(Base):
pk = Column(Integer, Sequence('foo'), primary_key=True)
ref = Column(Integer, index=True, nullable=False, default=-1)
@staticmethod
def fill_ref(mapper, connection, target):
# Note: You cannot use ORM in the event callbacks
connection.execute(mapper.mapped_table.update()
.values(ref=target.pk))
.where(table.c.pk==target.pk))
event.listen(Foo, 'after_insert', Foo.fill_ref)
答案 1 :(得分:1)
我建议使用触发器来设置该值。虽然我自己没有对此进行测试,但您可以使用触发器激活AFTER INSERT来读取新行的PK值并使用该值更新ref列。它似乎有点类似于Postgresql insert trigger to set value,除了你想要触发器在插入之后,而不是之前。