Может ли SQLAlchemy's session.merge () обновить свой результат с новыми данными из базы данных?

В документации SQLAlchemy говорится: « session.merge () сверяет текущее состояние экземпляра и связанных с ним дочерних элементов с существующими данными в базе данных».

Обновляется ли состояние существующего объекта новыми данными из базы данных? Как? Когда?

  • Многопоточное использование SQLAlchemy
  • Задайте запрос SQLAlchemy, укажите имена столбцов
  • Какова ваша папка для приложения Flask, разделенная на модули?
  • Операция Redshift COPY не работает в SQLAlchemy
  • Может ли SQLAlchemy объекты DateTime быть наивными?
  • Как разбивать страницы на Flask-SQLAlchemy для связанных с db.session запросов?
  • SQLAlchemy Reflection: как я могу запрашивать данные из определенных столбцов?
  • Комплексный запрос (подзапросы, функции окна) с sqlalchemy
  • 2 Solutions collect form web for “Может ли SQLAlchemy's session.merge () обновить свой результат с новыми данными из базы данных?”

    SQLAlchemy предназначен для создания единого объекта с каждым идентификатором в сеансе. Но иногда вам нужно воссоздать объект с известной идентификацией, например, когда вы получаете его из сети или когда вы реализуете автономную блокировку, чтобы избежать длительных транзакций. И когда вы создаете объект с известным идентификатором, который может существовать в базе данных, есть вероятность, что сеанс уже отслеживает объект с этим идентификатором. Это метод merge() для: он возвращает объект, прикрепленный к сеансу, что позволяет избежать дублирования объектов с одинаковым идентификатором в сеансе. Ниже приведен пример, иллюстрирующий, что происходит:

     from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData() t = Table( 't', metadata, Column('id', Integer, primary_key=True), Column('state', String(10)), ) class Model(object): pass mapper(Model, t) engine = create_engine('sqlite://') metadata.create_all(engine) session = sessionmaker(bind=engine)() obj1 = Model() obj1.state = 'value1' session.add(obj1) session.commit() obj_id = obj1.id obj2 = Model() obj2.id = obj_id obj2.state = 'value2' obj3 = session.merge(obj2) session.commit() print obj3 is obj1, obj3 is obj2 print obj3.state 

    Выход:

     True False value2 

    Таким образом, session.merge(obj2) обнаруживает, что существует объект с тем же идентификатором ( obj1 созданный выше), поэтому он объединяет состояние obj2 в существующий объект и возвращает его.

    Ниже приведен еще один пример, иллюстрирующий состояние загрузки из базы данных:

     # ...skipped... t = Table( 't', metadata, Column('id', Integer, primary_key=True), Column('state1', String(10)), Column('state2', String(10)), ) # ...skipped... obj1 = Model() obj1.state1 = 'value1-1' obj1.state2 = 'value2-1' session.add(obj1) session.commit() obj_id = obj1.id session.expunge_all() obj2 = Model() obj2.id = obj_id obj2.state1 = 'value1-2' obj3 = session.merge(obj2) session.commit() print obj3 is obj1, obj3 is obj2 print obj3.state1, obj3.state2 

    Выход:

     False False value1-2 value2-1 

    Теперь merge() не нашел объект с тем же идентификатором в сеансе, так как мы его исключили. Также я создал новый объект с частично назначенным состоянием, но остальное загружается из базы данных.

    Одна вещь, которую я заметил о слиянии, заключается в том, что даже доступ к полю на непривязанный объект приведет к его изменению во время слияния.

    Например, если у меня есть простой класс

     class X(Base): __tablename__= 'x' id = Column(Integer, primary_key=True) name = Column(String) value = Column(String) 

    и ряд

     (1, 'foo', 'bar') 

    то следующее, кажется, сливается красиво:

     x = X(id=1) merged_x = session.merge(x) print merged_x.name # 'foo' print merged_x.description # 'bar' 

    Но если я даже прочитаю имя или описание, это произойдет

     x = X(id=1) print x.name # None merged_x = session.merge(x) print merged_x.name # None print merged_x.description # 'bar' 

    Это противоречиво и, я бы сказал, неверно. Есть ли способ отключить это поведение? По-видимому, простое наличие атрибута в __dict__ заставляет это произойти. Эта «особенность» должна быть указана в документации.

    Python - лучший язык программирования в мире.