SQLAlchemy ORM:使用内联SELECT在INSERT语句中重用VALUES参数

时间:2015-06-02 11:16:11

标签: python sqlalchemy flask-sqlalchemy

我想使用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)

0 个答案:

没有答案