sql >> Base de Datos >  >> RDS >> PostgreSQL

Flask-SQLAlchemy db.session.query (Modelo) vs Model.query

A continuación se muestra la forma correcta de realizar cambios en una instancia de modelo y enviarlos a la base de datos:

# get an instance of the 'Entry' model
entry = Entry.query.get(1)

# change the attribute of the instance; here the 'name' attribute is changed
entry.name = 'New name'

# now, commit your changes to the database; this will flush all changes 
# in the current session to the database
db.session.commit()

Nota: No use SQLALCHEMY_COMMIT_ON_TEARDOWN , ya que se considera dañino y también se elimina de los documentos. Consulte el registro de cambios para la versión 2.0 .

Editar: Si tienes dos objetos de sesión normal (creado usando sessionmaker() ) en lugar de sesión con ámbito , luego al llamar a db.session.add(entry) el código anterior generará el error sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3') . Para comprender mejor la sesión de sqlalchemy, lea la siguiente sección

Gran diferencia entre la sesión con ámbito y la sesión normal

El objeto de sesión que construimos principalmente a partir de sessionmaker() llamada y utilizada para comunicarse con nuestra base de datos es una sesión normal . Si llama a sessionmaker() una segunda vez, obtendrá un nuevo objeto de sesión cuyos estados son independientes de la sesión anterior. Por ejemplo, supongamos que tenemos dos objetos de sesión construidos de la siguiente manera:

from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String)


from sqlalchemy import create_engine
engine = create_engine('sqlite:///')

from sqlalchemy.orm import sessionmaker
session = sessionmaker()
session.configure(bind=engine)
Base.metadata.create_all(engine)

# Construct the first session object
s1 = session()
# Construct the second session object
s2 = session()

Entonces, no podremos agregar el mismo objeto Usuario a ambos s1 y s2 al mismo tiempo. En otras palabras, un objeto solo se puede adjuntar como máximo a un único objeto de sesión.

>>> jessica = User(name='Jessica')
>>> s1.add(jessica)
>>> s2.add(jessica)
Traceback (most recent call last):
......
sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3')

Si los objetos de la sesión se recuperan de una scoped_session objeto, sin embargo, entonces no tenemos tal problema desde la scoped_session objeto mantiene un registro para el mismo objeto de sesión.

>>> session_factory = sessionmaker(bind=engine)
>>> session = scoped_session(session_factory)
>>> s1 = session()
>>> s2 = session()
>>> jessica = User(name='Jessica')
>>> s1.add(jessica)
>>> s2.add(jessica)
>>> s1 is s2
True
>>> s1.commit()
>>> s2.query(User).filter(User.name == 'Jessica').one()

Observe que s1 y s2 son el mismo objeto de sesión ya que ambos se recuperan de una scoped_session objeto que mantiene una referencia al mismo objeto de sesión.

Consejos

Por lo tanto, trate de evitar crear más de una sesión normal objeto. Cree un objeto de la sesión y utilícelo en todas partes, desde declarar modelos hasta realizar consultas.