PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

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

Di seguito è riportato il modo corretto per apportare modifiche a un'istanza del modello e salvarle nel database:

# 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: Non utilizzare SQLALCHEMY_COMMIT_ON_TEARDOWN , in quanto considerato dannoso e rimosso anche dai documenti. Vedi il log delle modifiche per la versione 2.0 .

Modifica: Se hai due oggetti di sessione normale (creato usando sessionmaker() ) invece di sessione con ambito , quindi chiamando db.session.add(entry) il codice precedente genererà l'errore sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3') . Per ulteriori informazioni sulla sessione di sqlalchemy, leggi la sezione sottostante

Grande differenza tra sessione con ambito e sessione normale

L'oggetto sessione che abbiamo costruito principalmente da sessionmaker() chiamata e utilizzata per comunicare con il nostro database è una sessione normale . Se chiami sessionmaker() una seconda volta, otterrai un nuovo oggetto sessione i cui stati sono indipendenti dalla sessione precedente. Ad esempio, supponiamo di avere due oggetti sessione costruiti nel modo seguente:

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()

Quindi, non saremo in grado di aggiungere lo stesso oggetto Utente a entrambi s1 e s2 allo stesso tempo. In altre parole, un oggetto può essere allegato al massimo a un unico oggetto sessione.

>>> 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')

Se gli oggetti sessione vengono recuperati da una scoped_session oggetto, tuttavia, non abbiamo un problema del genere poiché scoped_session object mantiene un registro per lo stesso oggetto sessione.

>>> 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()

Nota ches1 e s2 sono lo stesso oggetto sessione poiché sono entrambi recuperati da una scoped_session oggetto che mantiene un riferimento allo stesso oggetto sessione.

Suggerimenti

Quindi, cerca di evitare di creare più di una sessione normale oggetto. Crea un oggetto della sessione e utilizzalo ovunque, dalla dichiarazione dei modelli alle query.