我想使用SQLAlchemy ORM进行插入,使用依赖于其他值之一的内联select语句查找默认值。例如:
INSERT INTO foo (template_id, bar)
VALUES (%(template_id)s,
(SELECT template.bar_default
FROM template
WHERE template.id = %(template_id)s))
RETURNING foo.id
Enums in Javascript - Stijn de Witt's Blog,例如select()
,因此我考虑将其设置为:select([Template.bar_default]).where(Template.id == bindparam('template_id')
,如下所示:
class Template(sa.Model):
id = sa.Column(sa.Integer, primary_key=True)
bar_default = sa.Column(sa.String(20))
class Foo(sa.Model):
id = sa.Column(sa.Integer, primary_key=True)
template_id = sa.Column(sa.Integer, sa.ForeignKey(Template.id))
bar = sa.Column(sa.String(20),
default=select([Template.bar_default])
.where(Template.id == bindparam('template_id'))))
但是,这种方法不起作用。它失败并出现以下异常:
sqlalchemy.exc.CompileError:bindparam()name' template_id'是 保留用于VALUES或SET子句中的自动使用 插入/更新语句。请使用列名以外的名称 使用bindparam()与insert()或update()时(例如, ' b_template_id'。)
bindparam()
拒绝允许重新使用VALUES中的名称,即使这正是我在这里所需要的。有没有办法避免异常?
我的解决方法现在正如@lrnzcig所建议的那样:
def before_insert_listener(mapper, connection, target):
if target.template_id and not target.bar:
target.bar = select([Template.bar_default])\
.where(Template.id == target.template_id)
event.listen(Foo, 'before_insert', before_insert_listener)