Как я могу переключить два поля уникальной строки в пределах одного коммита, используя SQLAlchemy? - PullRequest
6 голосов
/ 02 февраля 2012

Предполагается иметь объект с уникальным именем.Теперь вы хотите изменить имя двух объектов:

Вот макет:

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.Есть ли способ переключить эти поля в пределах одного коммита без этой ошибки?

Ответы [ 3 ]

4 голосов
/ 02 февраля 2012

Вы указали 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.
4 голосов
/ 04 февраля 2012

Более простой вариант - удалить 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()
1 голос
/ 02 февраля 2012

Python разрешает этот синтаксис (с использованием кортежей):

a.name, b.name = b.name, a.name

Совершенно нормально переключать два нормальных аргумента таким образом, но в вашей ситуации это не проверялось, может быть, вы можете попробовать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...