Níže je uveden správný způsob, jak provést změny v instanci modelu a odeslat je do databáze:
# 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()
Poznámka: Nepoužívejte SQLALCHEMY_COMMIT_ON_TEARDOWN
, protože je považován za škodlivý a také odstraněn z dokumentů. Viz protokol změn verze 2.0
.
Upravit: Pokud máte dva objekty normální relace (vytvořeno pomocí sessionmaker()
) namísto relace v rozsahu a poté zavoláním db.session.add(entry)
výše uvedený kód vyvolá chybu sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3')
. Další informace o relaci sqlalchemy naleznete níže v sekci
Velký rozdíl mezi omezenou relací a normální relací
Objekt relace jsme většinou vytvořili z sessionmaker()
volání a používané ke komunikaci s naší databází je normální relace . Pokud zavoláte sessionmaker()
podruhé získáte nový objekt relace, jehož stavy jsou nezávislé na předchozí relaci. Předpokládejme například, že máme dva objekty relace vytvořené následujícím způsobem:
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()
Potom nebudeme moci přidat stejný objekt uživatele do obou s1
a s2
ve stejnou dobu. Jinými slovy, k objektu lze připojit maximálně jeden jedinečný objekt relace.
>>> 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')
Pokud jsou objekty relace načteny z scoped_session
objekt, pak však od scoped_session
takový problém nemáme objekt udržuje registr pro stejný objekt relace.
>>> 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()
Všimněte si, že s1
a s2
jsou stejným objektem relace, protože jsou oba načteny z scoped_session
objekt, který udržuje odkaz na stejný objekt relace.
Tipy
Snažte se tedy vyhnout vytvoření více než jedné normální relace objekt. Vytvořte jeden objekt relace a použijte jej všude od deklarování modelů po dotazování.