Nedenfor er den korrekte måde at foretage ændringer på en modelforekomst og forpligte dem til databasen:
# 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()
Bemærk: Brug ikke SQLALCHEMY_COMMIT_ON_TEARDOWN
, da det anses for at være skadeligt og også fjernet fra dokumenter. Se ændringsloggen for version 2.0
.
Rediger: Hvis du har to objekter af normal session (oprettet ved hjælp af sessionmaker()
) i stedet for session med omfang , og derefter ved at kalde db.session.add(entry)
ovenstående kode vil give fejlen sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3')
. For mere forståelse om sqlalchemy session, læs nedenstående afsnit
Stor forskel mellem omfangssession vs normal session
Sessionsobjektet konstruerede vi for det meste fra sessionmaker()
opkald og bruges til at kommunikere med vores database er en normal session . Hvis du kalder sessionmaker()
en anden gang vil du få et nyt sessionsobjekt, hvis tilstande er uafhængige af den forrige session. Antag for eksempel, at vi har to sessionsobjekter konstrueret på følgende måde:
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()
Så vil vi ikke være i stand til at tilføje det samme brugerobjekt til begge s1
og s2
på samme tid. Med andre ord kan et objekt højst vedhæftes ét unikt sessionsobjekt.
>>> 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')
Hvis sessionsobjekterne hentes fra en scoped_session
objekt, så har vi ikke et sådant problem siden scoped_session
objekt vedligeholder et register for det samme sessionsobjekt.
>>> 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()
Bemærk at s1
og s2
er det samme sessionsobjekt, da de begge er hentet fra en scoped_session
objekt, der opretholder en reference til det samme sessionsobjekt.
Tips
Så prøv at undgå at oprette mere end én normal session objekt. Opret ét objekt i sessionen, og brug det overalt fra deklarerende modeller til forespørgsler.