Vous trouverez ci-dessous la manière correcte d'apporter des modifications à une instance de modèle et de les valider dans la base de données :
# 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()
Remarque : N'utilisez pas SQLALCHEMY_COMMIT_ON_TEARDOWN
, car il est considéré comme nuisible et également supprimé des documents. Voir le journal des modifications pour la version 2.0
.
Modifier : Si vous avez deux objets de session normale (créé avec sessionmaker()
) au lieu de session délimitée , puis en appelant db.session.add(entry)
le code ci-dessus générera l'erreur sqlalchemy.exc.InvalidRequestError: Object '' is already attached to session '2' (this is '3')
. Pour plus de compréhension sur la session sqlalchemy, lisez la section ci-dessous
Différence majeure entre la session ciblée et la session normale
L'objet de session que nous avons principalement construit à partir de sessionmaker()
appel et utilisé pour communiquer avec notre base de données est une session normale . Si vous appelez sessionmaker()
une deuxième fois, vous obtiendrez un nouvel objet de session dont les états sont indépendants de la session précédente. Par exemple, supposons que nous ayons deux objets de session construits de la manière suivante :
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()
Ensuite, nous ne pourrons pas ajouter le même objet User aux deux s1
et s2
à la fois. En d'autres termes, un objet ne peut être attaché qu'à un seul objet de session unique.
>>> 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')
Si les objets de session sont récupérés depuis une scoped_session
objet, cependant, alors nous n'avons pas un tel problème depuis la scoped_session
objet maintient un registre pour le même objet de session.
>>> 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()
Notez ques1
et s2
sont le même objet de session puisqu'ils sont tous les deux extraits d'une scoped_session
objet qui maintient une référence au même objet de session.
Conseils
Essayez donc d'éviter de créer plus d'une session normale objet. Créez un objet de la session et utilisez-le partout, de la déclaration des modèles à l'interrogation.