sql >> Databasteknik >  >> RDS >> PostgreSQL

Flask-SQLAlchemy db.session.query(Model) vs Model.query

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.



  1. Hur kan denna fråga förbättras?

  2. Är det möjligt att använda resultatet av en SQL-funktion som ett fält i Doctrine?

  3. SQL:Gruppera liknande värden i kolumn B, men ordna efter kolumn A

  4. Hur man numrerar om en kolumn i doktrin