Poniżej znajduje się prawidłowy sposób wprowadzania zmian w instancji modelu i zatwierdzania ich w bazie danych:
# 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()
Uwaga: Nie używaj SQLALCHEMY_COMMIT_ON_TEARDOWN
, ponieważ jest uważana za szkodliwą i usuwana z dokumentów. Zobacz dziennik zmian dla wersji 2.0
.
Edytuj: Jeśli masz dwa obiekty normalnej sesji (utworzony za pomocą sessionmaker()
) zamiast sesja w zakresie , a następnie przy wywołaniu db.session.add(entry)
powyższy kod zgłosi błąd sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3')
. Aby uzyskać więcej informacji na temat sesji sqlalchemy, przeczytaj poniżej sekcję
Główna różnica między sesją z zakresem a sesją normalną
Obiekt sesji, który w większości skonstruowaliśmy z sessionmaker()
połączenie i używane do komunikacji z naszą bazą danych to normalna sesja . Jeśli wywołasz sessionmaker()
po raz drugi otrzymasz nowy obiekt sesji, którego stany są niezależne od poprzedniej sesji. Załóżmy na przykład, że mamy dwa obiekty sesyjne skonstruowane w następujący sposób:
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()
Wtedy nie będziemy mogli dodać tego samego obiektu użytkownika do obu s1
i s2
w tym samym czasie. Innymi słowy, obiekt może być dołączony tylko do jednego unikalnego obiektu sesji.
>>> 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')
Jeśli obiekty sesji są pobierane z scoped_session
obiekt, jednak nie mamy takiego problemu od czasu scoped_session
obiekt prowadzi rejestr dla tego samego obiektu sesji.
>>> 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()
Zauważ, żes1
i s2
są tym samym obiektem sesji, ponieważ oba są pobierane z scoped_session
obiekt, który utrzymuje odniesienie do tego samego obiektu sesji.
Wskazówki
Staraj się więc unikać tworzenia więcej niż jednej normalnej sesji obiekt. Utwórz jeden obiekt sesji i używaj go wszędzie, od deklarowania modeli po zapytania.