Phi*_*erg 6 python sqlalchemy unique-constraint
假设有一个具有唯一名称的对象.现在要切换两个对象的名称:
这是布局:
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()
Run Code Online (Sandbox Code Playgroud)
我想这样做:
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()
Run Code Online (Sandbox Code Playgroud)
这引发了IntegrityError.有没有办法在一次提交中切换这些字段而没有此错误?
更纯粹的选择是删除 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()
Run Code Online (Sandbox Code Playgroud)
您输入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.
Run Code Online (Sandbox Code Playgroud)