PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

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

Unten ist die richtige Methode, um Änderungen an einer Modellinstanz vorzunehmen und sie in die Datenbank zu übernehmen:

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

Hinweis: Verwenden Sie nicht SQLALCHEMY_COMMIT_ON_TEARDOWN , da es als schädlich angesehen und auch aus der Dokumentation entfernt wurde. Siehe das Änderungsprotokoll für Version 2.0 .

Bearbeiten: Wenn Sie zwei Objekte einer normalen Sitzung haben (erstellt mit sessionmaker() ) statt begrenzte Sitzung , dann beim Aufruf von db.session.add(entry) Der obige Code löst den Fehler sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3') aus . Weitere Informationen zur sqlalchemy-Sitzung finden Sie im folgenden Abschnitt

Großer Unterschied zwischen Scoped Session und normaler Session

Das Session-Objekt haben wir meistens aus dem sessionmaker() konstruiert anrufen und zur Kommunikation mit unserer Datenbank verwendet werden, ist eine normale Sitzung . Wenn Sie sessionmaker() aufrufen ein zweites Mal erhalten Sie ein neues Sitzungsobjekt, dessen Zustände unabhängig von der vorherigen Sitzung sind. Nehmen wir zum Beispiel an, wir haben zwei Sitzungsobjekte, die wie folgt aufgebaut sind:

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

Dann können wir dasselbe Benutzerobjekt nicht beiden s1 hinzufügen und s2 zur selben Zeit. Mit anderen Worten, einem Objekt kann höchstens ein eindeutiges Sitzungsobjekt zugeordnet werden.

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

Wenn die Sitzungsobjekte von einer scoped_session abgerufen werden object, dann haben wir ein solches Problem jedoch seit scoped_session nicht mehr Objekt verwaltet eine Registrierung für dasselbe Sitzungsobjekt.

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

Beachten Sie, dasss1 und s2 sind dasselbe Sitzungsobjekt, da sie beide von einer scoped_session abgerufen werden Objekt, das einen Verweis auf dasselbe Sitzungsobjekt verwaltet.

Tipps

Versuchen Sie also zu vermeiden, mehr als eine normale Sitzung zu erstellen Objekt. Erstellen Sie ein Objekt der Sitzung und verwenden Sie es überall, vom Deklarieren von Modellen bis zum Abfragen.