Использование сессии - PullRequest
       1

Использование сессии

0 голосов
/ 16 января 2020

Я использую sqlalchemy 1.3.0 с postgres 11. Я пытаюсь использовать INSERT с ON CONFLICT DO UPDATE ... RETURNING * для создания экземпляра моей модели.

class Model(Base):
    __tablename__ = 'mytable'
    pk = Column(String(64), primary_key=True)
    col2 = Column(String(64))

    @classmethod
    def upsert(cls, pk, col2, session):
        return session.query(cls).from_statement(
            text(
                """
                INSERT INTO {} (pk, col2) VALUES (:pk, :col2)
                ON CONFLICT (pk) DO UPDATE SET col2=EXCLUDED.col2 RETURNING *;
                """.format(cls.__tablename__)
            )
        ).params(pk=pk, col2=col2).one()

obj1 = Model.upsert(1, 'one', session)
obj2 = Model.upsert(1, 'two', session)
print(obj2.col2) ----> outputs "one"
session.commit()
print(obj2.col2) ----> outputs "two"

Второй upsert выдает правильную команду для базы данных, но при печати атрибута col2 возвращаемого объекта отображается значение столбца, который был вставлен во время first upsert. Затем, если я сделаю session.commit(), объект волшебным образом обновится, чтобы показать новое значение. Что мне не хватает? Я хочу, чтобы объект, возвращаемый функцией, отражал значения, до которых была обновлена ​​строка, без необходимости выполнения коммита, потому что я хочу, чтобы это наряду с некоторыми другими вещами происходило в транзакции.

1 Ответ

0 голосов
/ 16 января 2020

Оказывается, что session.commit() по существу истекал объект, так что следующий print(obj2.col2) запросит базу данных для заполнения ее атрибутов.

Чтобы obj2.col2 было правильным значением без Принимая (и запрашивая базу данных), мне просто нужно было сделать session.expunge(obj1) перед вторым вызовом upsert для создания obj2.

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