如何使用SQLAlchemy在一次提交中切换唯一行的两个字段?

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.有没有办法在一次提交中切换这些字段而没有此错误?

Mu *_*ind 5

更纯粹的选择是删除 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)


Nil*_*esh 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.
Run Code Online (Sandbox Code Playgroud)