Nedan är det korrekta sättet att göra ändringar i en modellinstans och överföra dem till 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()
Obs! Använd inte SQLALCHEMY_COMMIT_ON_TEARDOWN
, eftersom det anses vara skadligt och även tagits bort från dokument. Se ändringsloggen för version 2.0
.
Redigera: Om du har två objekt för normal session (skapat med sessionmaker()
) istället för omfattad session , sedan när du anropar db.session.add(entry)
ovanstående kod ger upphov till felet sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3')
. För mer förståelse om sqlalchemy-session, läs avsnittet nedan
Större skillnad mellan scoped session kontra normal session
Sessionsobjektet konstruerade vi mestadels från sessionmaker()
samtal och används för att kommunicera med vår databas är en normal session . Om du anropar sessionmaker()
en andra gång får du ett nytt sessionsobjekt vars tillstånd är oberoende av föregående session. Anta till exempel att vi har två sessionsobjekt konstruerade på följande sätt:
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()
Då kommer vi inte att kunna lägga till samma användarobjekt till båda s1
och s2
på samma gång. Med andra ord kan ett objekt endast bifogas högst ett 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')
Om sessionsobjekten hämtas från en scoped_session
objekt, men då har vi inte ett sådant problem sedan scoped_session
object upprätthåller ett register för samma 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()
Lägg märke till att s1
och s2
är samma sessionsobjekt eftersom de båda hämtas från en scoped_session
objekt som upprätthåller en referens till samma sessionsobjekt.
Tips
Så försök att undvika att skapa mer än en normal session objekt. Skapa ett objekt i sessionen och använd det överallt från deklarationsmodeller till sökningar.