假设有一个具有唯一名称的对象。现在要切换两个对象的名称:
这是布局:
import sqlalchemy as sa
import sqlalchemy.orm as orm
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class MyObject(Base):
__tablename__ = 'my_objects'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Text, unique=True)
if __name__ == "__main__":
engine = sa.create_engine('sqlite:///:memory:', echo=True)
Session = orm.sessionmaker(bind=engine)
Base.metadata.create_all(engine)
session = Session()
我想这样做:
a = MyObject(name="Max")
b = MyObject(name="Moritz")
session.add_all([a, b])
session.commit()
# Now: switch names!
tmp = a.name
a.name = b.name
b.name = tmp
session.commit()
这会引发IntegrityError
。有没有办法在一次提交中切换这些字段而没有这个错误?
答案 0 :(得分:4)
您在名称字段中提供了unique=True
,因此当您尝试提交时,它将运行更新查询,这将引发错误。
情况是您更改将在内存中设置的名称。但是当它尝试运行更新查询时,旧记录已经存在,并且具有相同的名称,因此它将提供IntegrityError
。
更改名称的方法是
a = MyObject(name="Max")
b = MyObject(name="Moritz")
session.add_all([a, b])
session.commit()
# Now: switch names!
atmp = a.name
btemp = b.name
a.name = a.name+btemp # Temp set the any random name
session.commit()
b.name = atemp
a.name = btemp
session.commit() # Run the update query for update the record.
答案 1 :(得分:4)
更纯粹的选择是删除a,重命名b,然后重新添加重命名的:
session.delete(a)
sqlalchemy.orm.session.make_transient(a)
a.name, b.name = b.name, a.name
session.flush()
session.add(a)
session.commit()
答案 2 :(得分:1)
Python允许这种语法(使用元组):
a.name, b.name = b.name, a.name
以这种方式切换两个普通参数是绝对可以的,但是在你的情况下没有测试过,也许你可以尝试一下?