Kontextuelle/Thread-lokale Sessions

Aus dem Abschnitt Wann erstelle ich eine Session, wann committe ich sie und wann schließe ich sie? erinnern wir uns an das Konzept der „Session-Geltungsbereiche“, mit besonderem Fokus auf Webanwendungen und die Praxis, den Geltungsbereich einer Session mit dem einer Webanfrage zu verknüpfen. Die meisten modernen Web-Frameworks enthalten Integrationstools, damit der Geltungsbereich der Session automatisch verwaltet werden kann, und diese Tools sollten verwendet werden, sobald sie verfügbar sind.

SQLAlchemy enthält ein eigenes Hilfsobjekt, das bei der Einrichtung benutzerdefinierter Session-Geltungsbereiche hilft. Es wird auch von Drittanbieter-Integrationssystemen verwendet, um ihre Integrationsschemata zu erstellen.

Das Objekt ist das scoped_session-Objekt und repräsentiert eine Registry von Session-Objekten. Wenn Sie mit dem Registry-Muster nicht vertraut sind, finden Sie eine gute Einführung in Patterns of Enterprise Architecture.

Warnung

Die scoped_session-Registry verwendet standardmäßig ein Python-Objekt threading.local(), um Session-Instanzen zu verfolgen. Dies ist nicht unbedingt mit allen Anwendungsservern kompatibel, insbesondere mit denen, die Greenlets oder andere alternative Formen der Nebenläufigkeitssteuerung verwenden, was zu Race Conditions (z. B. zufälligen Fehlern) führen kann, wenn es in Szenarien mit moderater bis hoher Nebenläufigkeit verwendet wird. Bitte lesen Sie Thread-lokaler Geltungsbereich und Verwendung des thread-lokalen Geltungsbereichs mit Webanwendungen unten, um die Auswirkungen der Verwendung von threading.local() zur Verfolgung von Session-Objekten vollständig zu verstehen und erwägen Sie explizitere Mittel der Geltungsbereichszuweisung, wenn Sie Anwendungsserver verwenden, die nicht auf traditionellen Threads basieren.

Hinweis

Das scoped_session-Objekt ist ein sehr beliebtes und nützliches Objekt, das von vielen SQLAlchemy-Anwendungen verwendet wird. Es ist jedoch wichtig zu beachten, dass es nur einen Ansatz für die Verwaltung von Session-Objekten darstellt. Wenn Sie neu bei SQLAlchemy sind und besonders wenn der Begriff „thread-lokale Variable“ Ihnen seltsam erscheint, empfehlen wir Ihnen, sich, wenn möglich, zuerst mit einem fertigen Integrationstool wie Flask-SQLAlchemy oder zope.sqlalchemy vertraut zu machen.

Ein scoped_session wird erstellt, indem es aufgerufen wird und eine Factory übergeben wird, die neue Session-Objekte erstellen kann. Eine Factory ist einfach etwas, das beim Aufruf ein neues Objekt produziert, und im Fall von Session ist die gebräuchlichste Factory die sessionmaker, die bereits in diesem Abschnitt vorgestellt wurde. Nachfolgend illustrieren wir diese Verwendung

>>> from sqlalchemy.orm import scoped_session
>>> from sqlalchemy.orm import sessionmaker

>>> session_factory = sessionmaker(bind=some_engine)
>>> Session = scoped_session(session_factory)

Das erstellte scoped_session-Objekt wird nun die sessionmaker aufrufen, wenn wir die Registry „aufrufen“

>>> some_session = Session()

Oben ist some_session eine Instanz von Session, die wir nun zur Kommunikation mit der Datenbank verwenden können. Dieselbe Session ist auch innerhalb der von uns erstellten scoped_session-Registry vorhanden. Wenn wir die Registry ein zweites Mal aufrufen, erhalten wir dieselbe Session zurück

>>> some_other_session = Session()
>>> some_session is some_other_session
True

Dieses Muster ermöglicht es verschiedenen Teilen der Anwendung, eine globale scoped_session aufzurufen, sodass alle diese Bereiche dieselbe Session gemeinsam nutzen können, ohne sie explizit übergeben zu müssen. Die von uns in unserer Registry eingerichtete Session bleibt erhalten, bis wir unserer Registry explizit befehlen, sie zu entsorgen, indem wir scoped_session.remove() aufrufen.

>>> Session.remove()

Die Methode scoped_session.remove() ruft zuerst Session.close() auf der aktuellen Session auf, was zur Folge hat, dass zunächst alle von der Session gehaltenen Verbindungs-/Transaktionsressourcen freigegeben werden und dann die Session selbst verworfen wird. „Freigeben“ bedeutet hier, dass Verbindungen zu ihrem Connection-Pool zurückgegeben und jeglicher Transaktionszustand zurückgerollt wird, wobei letztendlich die Methode rollback() der zugrundeliegenden DBAPI-Verbindung verwendet wird.

Zu diesem Zeitpunkt ist das scoped_session-Objekt „leer“ und erstellt eine neue Session, wenn es erneut aufgerufen wird. Wie unten gezeigt, ist dies nicht dieselbe Session, die wir zuvor hatten

>>> new_session = Session()
>>> new_session is some_session
False

Die obige Schrittfolge veranschaulicht das Konzept des „Registry“-Musters in Kurzform. Mit dieser grundlegenden Idee können wir einige Details besprechen, wie dieses Muster vorgeht.

Impliziter Methodenaufruf

Die Aufgabe der scoped_session ist einfach; sie hält eine Session für alle, die sie anfordern. Um einen transparenteren Zugriff auf diese Session zu ermöglichen, enthält die scoped_session auch ein Proxy-Verhalten, was bedeutet, dass die Registry selbst wie eine Session behandelt werden kann; wenn Methoden auf diesem Objekt aufgerufen werden, werden sie an die zugrundeliegende Session, die von der Registry verwaltet wird, weitergeleitet.

Session = scoped_session(some_factory)

# equivalent to:
#
# session = Session()
# print(session.scalars(select(MyClass)).all())
#
print(Session.scalars(select(MyClass)).all())

Der obige Code erreicht dasselbe wie das Abrufen der aktuellen Session, indem die Registry aufgerufen und dann diese Session verwendet wird.

Thread-lokaler Geltungsbereich

Benutzer, die mit multithreaded Programmierung vertraut sind, werden feststellen, dass die Darstellung von etwas als globale Variable normalerweise eine schlechte Idee ist, da dies impliziert, dass das globale Objekt von vielen Threads gleichzeitig aufgerufen wird. Das Session-Objekt ist vollständig für die Verwendung in einer nicht-gleichzeitigen Weise konzipiert, was im Hinblick auf Multithreading bedeutet: „nur in einem Thread zu einer Zeit“. Unser obiges Beispiel für die Verwendung von scoped_session, bei dem dieselbe Session über mehrere Aufrufe hinweg beibehalten wird, legt nahe, dass ein Prozess vorhanden sein muss, der sicherstellt, dass mehrere Aufrufe über viele Threads hinweg nicht tatsächlich auf dieselbe Session zugreifen. Wir nennen diese Vorstellung thread-lokalen Speicher, was bedeutet, dass ein spezielles Objekt verwendet wird, das pro Anwendungsthread ein separates Objekt verwaltet. Python bietet dies über den Konstrukt threading.local(). Das scoped_session-Objekt verwendet standardmäßig dieses Objekt als Speicher, sodass eine einzelne Session für alle, die die scoped_session-Registry aufrufen, beibehalten wird, aber nur innerhalb des Geltungsbereichs eines einzelnen Threads. Aufrufer, die die Registry in einem anderen Thread aufrufen, erhalten eine Session-Instanz, die für diesen anderen Thread lokal ist.

Mit dieser Technik bietet scoped_session eine schnelle und relativ einfache (wenn man mit thread-lokalem Speicher vertraut ist) Möglichkeit, ein einzelnes, globales Objekt in einer Anwendung bereitzustellen, das sicher von mehreren Threads aufgerufen werden kann.

Die Methode scoped_session.remove() entfernt wie immer die aktuell mit dem Thread verknüpfte Session, falls vorhanden. Ein Vorteil des threading.local()-Objekts ist jedoch, dass der „Speicher“ für diesen Thread auch dann garbage collected wird, wenn der Anwendungsthread selbst endet. Daher ist es „sicher“, den thread-lokalen Geltungsbereich mit einer Anwendung zu verwenden, die Threads erzeugt und beendet, ohne scoped_session.remove() aufrufen zu müssen. Der Geltungsbereich von Transaktionen selbst, d. h. das Beenden über Session.commit() oder Session.rollback(), wird jedoch normalerweise immer noch etwas sein, das zum richtigen Zeitpunkt explizit arrangiert werden muss, es sei denn, die Anwendung bindet die Lebensdauer eines Threads tatsächlich an die Lebensdauer einer Transaktion.

Verwendung des thread-lokalen Geltungsbereichs mit Webanwendungen

Wie im Abschnitt Wann erstelle ich eine Session, wann committe ich sie und wann schließe ich sie? erläutert, ist eine Webanwendung um das Konzept einer Webanfrage herum aufgebaut, und die Integration einer solchen Anwendung mit der Session impliziert in der Regel, dass die Session mit dieser Anfrage verknüpft wird. Wie sich herausstellt, verwenden die meisten Python-Web-Frameworks, mit bemerkenswerten Ausnahmen wie den asynchronen Frameworks Twisted und Tornado, Threads auf einfache Weise, sodass eine bestimmte Webanfrage innerhalb des Geltungsbereichs eines einzelnen Worker-Threads empfangen, verarbeitet und abgeschlossen wird. Wenn die Anfrage endet, wird der Worker-Thread an einen Pool von Workern zurückgegeben, wo er zur Bearbeitung einer anderen Anfrage zur Verfügung steht.

Diese einfache Entsprechung von Webanfrage und Thread bedeutet, dass die Verknüpfung einer Session mit einem Thread impliziert, dass sie auch mit der Webanfrage verknüpft ist, die innerhalb dieses Threads läuft, und umgekehrt, vorausgesetzt, dass die Session erst nach Beginn der Webanfrage erstellt und kurz vor Ende der Webanfrage abgebaut wird. Daher ist es eine gängige Praxis, scoped_session als schnelle Möglichkeit zur Integration der Session mit einer Webanwendung zu verwenden. Das folgende Sequenzdiagramm illustriert diesen Ablauf

Web Server          Web Framework        SQLAlchemy ORM Code
--------------      --------------       ------------------------------
startup        ->   Web framework        # Session registry is established
                    initializes          Session = scoped_session(sessionmaker())

incoming
web request    ->   web request     ->   # The registry is *optionally*
                    starts               # called upon explicitly to create
                                         # a Session local to the thread and/or request
                                         Session()

                                         # the Session registry can otherwise
                                         # be used at any time, creating the
                                         # request-local Session() if not present,
                                         # or returning the existing one
                                         Session.execute(select(MyClass)) # ...

                                         Session.add(some_object) # ...

                                         # if data was modified, commit the
                                         # transaction
                                         Session.commit()

                    web request ends  -> # the registry is instructed to
                                         # remove the Session
                                         Session.remove()

                    sends output      <-
outgoing web    <-
response

Mit dem obigen Ablauf hat die Integration der Session mit der Webanwendung genau zwei Anforderungen:

  1. Erstellen Sie beim ersten Start der Webanwendung eine einzige scoped_session-Registry, stellen Sie sicher, dass dieses Objekt für den Rest der Anwendung zugänglich ist.

  2. Stellen Sie sicher, dass scoped_session.remove() aufgerufen wird, wenn die Webanfrage endet, normalerweise durch Integration mit dem Ereignissystem des Web-Frameworks, um ein „Ereignis am Ende der Anfrage“ einzurichten.

Wie bereits erwähnt, ist das obige Muster nur eine mögliche Methode zur Integration einer Session mit einem Web-Framework, die insbesondere die wichtige Annahme trifft, dass das Web-Framework Webanfragen mit Anwendungsthreads verknüpft. Es wird jedoch dringend empfohlen, die vom Web-Framework selbst bereitgestellten Integrationstools zu verwenden, falls verfügbar, anstelle von scoped_session.

Insbesondere, während die Verwendung von Thread-lokalen Daten praktisch sein kann, ist es vorzuziehen, dass die Session direkt mit der Anfrage verknüpft wird, anstatt mit dem aktuellen Thread. Der nächste Abschnitt über benutzerdefinierte Geltungsbereiche beschreibt eine fortgeschrittenere Konfiguration, die die Verwendung von scoped_session mit direkt anfragebasiertem Geltungsbereich oder jeder Art von Geltungsbereich kombinieren kann.

Verwendung von benutzerdefinierten Geltungsbereichen

Das Standardverhalten des scoped_session-Objekts für „thread-lokalen“ Geltungsbereich ist nur eine von vielen Optionen, wie ein Session „Geltungsbereich“ zugewiesen werden kann. Ein benutzerdefinierter Geltungsbereich kann auf jedem vorhandenen System zum Abrufen von „dem aktuellen Ding, mit dem wir arbeiten“ basieren.

Angenommen, ein Web-Framework definiert eine Bibliotheksfunktion get_current_request(). Eine mit diesem Framework erstellte Anwendung kann diese Funktion jederzeit aufrufen, und das Ergebnis ist ein Request-Objekt, das die aktuell verarbeitete Anfrage darstellt. Wenn das Request-Objekt hashbar ist, kann diese Funktion einfach mit scoped_session integriert werden, um die Session mit der Anfrage zu verknüpfen. Unten illustrieren wir dies in Verbindung mit einem hypothetischen Ereignismarker, der vom Web-Framework on_request_end bereitgestellt wird, der es ermöglicht, Code aufzurufen, wann immer eine Anfrage endet.

from my_web_framework import get_current_request, on_request_end
from sqlalchemy.orm import scoped_session, sessionmaker

Session = scoped_session(sessionmaker(bind=some_engine), scopefunc=get_current_request)


@on_request_end
def remove_session(req):
    Session.remove()

Oben instanziieren wir scoped_session auf übliche Weise, außer dass wir unsere Anfragen zurückgebende Funktion als „scopefunc“ übergeben. Dies weist scoped_session an, diese Funktion zu verwenden, um einen Dictionary-Schlüssel zu generieren, wann immer die Registry aufgerufen wird, um die aktuelle Session zurückzugeben. In diesem Fall ist es besonders wichtig, dass wir ein zuverlässiges „remove“-System implementieren, da dieses Dictionary nicht anderweitig selbst verwaltet wird.

Kontextuelle Session-API

Objektname Beschreibung

QueryPropertyDescriptor

Beschreibt den Typ, der auf ein Klassenattribut scoped_session.query_property() angewendet wird.

scoped_session

Bietet eine bereichsbezogene Verwaltung von Session-Objekten.

ScopedRegistry

Eine Registry, die eine oder mehrere Instanzen einer einzelnen Klasse auf Basis einer „scope“-Funktion speichern kann.

ThreadLocalRegistry

Eine ScopedRegistry, die eine threading.local()-Variable zur Speicherung verwendet.

class sqlalchemy.orm.scoped_session

Bietet eine bereichsbezogene Verwaltung von Session-Objekten.

Siehe Kontextuelle/Thread-lokale Sessions für ein Tutorial.

Hinweis

Bei Verwendung von Asynchrones I/O (asyncio) sollte die asynchron kompatible Klasse async_scoped_session anstelle von scoped_session verwendet werden.

Klassensignatur

class sqlalchemy.orm.scoped_session (typing.Generic)

method sqlalchemy.orm.scoped_session.__call__(**kw: Any) _S

Gibt die aktuelle Session zurück und erstellt sie mithilfe der scoped_session.session_factory, falls sie nicht vorhanden ist.

Parameter:

**kw – Schlüsselwortargumente werden an den scoped_session.session_factory-Callable übergeben, falls keine vorhandene Session vorhanden ist. Wenn die Session vorhanden ist und Schlüsselwortargumente übergeben wurden, wird InvalidRequestError ausgelöst.

method sqlalchemy.orm.scoped_session.__init__(session_factory: sessionmaker[_S], scopefunc: Callable[[], Any] | None = None)

Konstruiert eine neue scoped_session.

Parameter:
  • session_factory – eine Factory zum Erstellen neuer Session-Instanzen. Dies ist normalerweise, aber nicht notwendigerweise, eine Instanz von sessionmaker.

  • scopefunc – optionale Funktion, die den aktuellen Geltungsbereich definiert. Wenn nicht übergeben, nimmt das scoped_session-Objekt einen „Thread-lokalen“ Geltungsbereich an und verwendet ein Python threading.local(), um die aktuelle Session zu verwalten. Wenn übergeben, sollte die Funktion einen Hash-Token zurückgeben; dieser Token wird als Schlüssel in einem Wörterbuch verwendet, um die aktuelle Session zu speichern und abzurufen.

method sqlalchemy.orm.scoped_session.add(instance: object, _warn: bool = True) None

Ein Objekt in diese Session einfügen.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Objekte, die sich im transienten Zustand befinden, wenn sie an die Methode Session.add() übergeben werden, wechseln in den ausstehenden Zustand, bis zum nächsten Flush, an dem sie in den persistenten Zustand wechseln.

Objekte, die sich im detached Zustand befinden, wenn sie an die Methode Session.add() übergeben werden, wechseln direkt in den persistenten Zustand.

Wenn die von der Session verwendete Transaktion zurückgerollt wird, werden Objekte, die transient waren, als sie an Session.add() übergeben wurden, wieder in den transienten Zustand versetzt und sind nicht mehr in dieser Session vorhanden.

method sqlalchemy.orm.scoped_session.add_all(instances: Iterable[object]) None

Die angegebene Sammlung von Instanzen zu dieser Session hinzufügen.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Siehe die Dokumentation für Session.add() für eine allgemeine Verhaltensbeschreibung.

attribute sqlalchemy.orm.scoped_session.autoflush

Proxy für das Attribut Session.autoflush im Auftrag der Klasse scoped_session.

method sqlalchemy.orm.scoped_session.begin(nested: bool = False) SessionTransaction

Eine Transaktion oder eine verschachtelte Transaktion auf dieser Session beginnen, falls noch keine begonnen wurde.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Das Session-Objekt bietet **Autobegin**-Verhalten, sodass es normalerweise nicht notwendig ist, die Methode Session.begin() explizit aufzurufen. Sie kann jedoch verwendet werden, um den Geltungsbereich zu steuern, wann der transaktionale Zustand begonnen wird.

Wenn sie verwendet wird, um die äußerste Transaktion zu beginnen, wird ein Fehler ausgelöst, wenn sich diese Session bereits innerhalb einer Transaktion befindet.

Parameter:

nested – wenn True, wird eine SAVEPOINT-Transaktion begonnen und ist äquivalent zum Aufruf von Session.begin_nested(). Weitere Informationen zu SAVEPOINT-Transaktionen finden Sie unter SAVEPOINT verwenden.

Gibt zurück:

das SessionTransaction-Objekt. Beachten Sie, dass SessionTransaction als Kontextmanager in Python fungiert, was es ermöglicht, Session.begin() in einem „with“-Block zu verwenden. Siehe Explizites Beginnen für ein Beispiel.

method sqlalchemy.orm.scoped_session.begin_nested() SessionTransaction

Eine „verschachtelte“ Transaktion auf dieser Session beginnen, z. B. SAVEPOINT.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Die Zieldatenbank(en) und zugehörigen Treiber müssen SQL SAVEPOINT unterstützen, damit diese Methode korrekt funktioniert.

Weitere Informationen zu SAVEPOINT-Transaktionen finden Sie unter SAVEPOINT verwenden.

Gibt zurück:

das SessionTransaction-Objekt. Beachten Sie, dass SessionTransaction als Kontextmanager fungiert, was es ermöglicht, Session.begin_nested() in einem „with“-Block zu verwenden. Siehe SAVEPOINT verwenden für ein Nutzungsbeispiel.

Siehe auch

SAVEPOINT verwenden

Serielle Isolation / Savepoints / Transaktionales DDL - spezielle Workarounds, die mit dem SQLite-Treiber erforderlich sind, damit SAVEPOINT korrekt funktioniert. Für Asyncio-Anwendungsfälle siehe den Abschnitt Serielle Isolation / Savepoints / Transaktionales DDL (Asyncio-Version).

attribute sqlalchemy.orm.scoped_session.bind

Proxy für das Attribut Session.bind im Auftrag der Klasse scoped_session.

method sqlalchemy.orm.scoped_session.bulk_insert_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]], return_defaults: bool = False, render_nulls: bool = False) None

Führt einen Massen-INSERT der gegebenen Liste von Mapping-Wörterbüchern durch.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Legacy-Funktion

Diese Methode ist eine Legacy-Funktion ab der 2.0-Serie von SQLAlchemy. Für moderne Massen-INSERT und UPDATE siehe die Abschnitte ORM Massen-INSERT-Anweisungen und ORM Massen-UPDATE nach Primärschlüssel. Die 2.0-API teilt Implementierungsdetails mit dieser Methode und fügt neue Funktionen hinzu.

Parameter:
  • mapper – eine gemappte Klasse oder das eigentliche Mapper-Objekt, das die einzige Art von Objekt repräsentiert, die in der Mapping-Liste enthalten ist.

  • mappings – eine Sequenz von Wörterbüchern, die jeweils den Zustand der abzubilden Zeile enthalten, die eingefügt werden soll, in Bezug auf die Attributnamen der abgebildeten Klasse. Wenn das Mapping mehrere Tabellen referenziert, wie z. B. ein Joined-Inheritance-Mapping, muss jedes Wörterbuch alle Schlüssel enthalten, die in alle Tabellen eingetragen werden sollen.

  • return_defaults

    wenn True, wird der INSERT-Prozess so geändert, dass sichergestellt wird, dass neu generierte Primärschlüsselwerte abgerufen werden. Der Grund für diesen Parameter ist typischerweise die Aktivierung von Massen-INSERTs für Joined Table Inheritance-Mappings.

    Hinweis

    für Backends, die RETURNING nicht unterstützen, kann der Parameter Session.bulk_insert_mappings.return_defaults die Leistung erheblich reduzieren, da INSERT-Anweisungen nicht mehr gestapelt werden können. Siehe „Insert Many Values“-Verhalten für INSERT-Anweisungen für Hintergrundinformationen, welche Backends betroffen sind.

  • render_nulls

    Wenn True, führt ein Wert von None dazu, dass ein NULL-Wert in die INSERT-Anweisung aufgenommen wird, anstatt die Spalte aus dem INSERT auszuschließen. Dies ermöglicht es allen eingefügten Zeilen, denselben Satz von Spalten zu haben, was es ermöglicht, den gesamten Satz von Zeilen an den DBAPI zu stapeln. Normalerweise muss jeder Spaltensatz, der eine andere Kombination von NULL-Werten als die vorherige Zeile enthält, eine andere Reihe von Spalten aus der gerenderten INSERT-Anweisung ausschließen, was bedeutet, dass er als separate Anweisung ausgegeben werden muss. Durch das Übergeben dieses Flags wird garantiert, dass der gesamte Satz von Zeilen in einen Stapel gestapelt werden kann; der Preis dafür ist jedoch, dass serverseitige Standardwerte, die durch eine ausgeschlossene Spalte aufgerufen werden, übersprungen werden. Daher ist Vorsicht geboten, um sicherzustellen, dass diese nicht notwendig sind.

    Warnung

    Wenn dieses Flag gesetzt ist, **werden serverseitige Standard-SQL-Werte nicht aufgerufen** für die Spalten, die als NULL eingefügt werden; der NULL-Wert wird explizit gesendet. Vorsicht ist geboten, um sicherzustellen, dass keine serverseitigen Standardfunktionen für die gesamte Operation aufgerufen werden müssen.

method sqlalchemy.orm.scoped_session.bulk_save_objects(objects: Iterable[object], return_defaults: bool = False, update_changed_only: bool = True, preserve_order: bool = True) None

Führt ein Massen-Speichern der gegebenen Liste von Objekten durch.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Legacy-Funktion

Diese Methode ist eine Legacy-Funktion ab der 2.0-Serie von SQLAlchemy. Für moderne Massen-INSERT und UPDATE siehe die Abschnitte ORM Massen-INSERT-Anweisungen und ORM Massen-UPDATE nach Primärschlüssel.

Für allgemeine INSERT und UPDATE von vorhandenen ORM-abgebildeten Objekten bevorzugen Sie Standardmuster für die Verwaltung von Unit of Work, eingeführt im Vereinigten SQLAlchemy-Tutorial unter Datenmanipulation mit dem ORM. SQLAlchemy 2.0 verwendet jetzt „Insert Many Values“-Verhalten für INSERT-Anweisungen mit modernen Dialekten, was frühere Probleme mit langsamen Massen-INSERTs löst.

Parameter:
  • objects

    eine Sequenz von abgebildeten Objektinstanzen. Die abgebildeten Objekte werden so gespeichert, wie sie sind, und sind danach **nicht** mit der Session verbunden.

    Für jedes Objekt hängt die Entscheidung, ob das Objekt als INSERT oder UPDATE gesendet wird, von denselben Regeln ab, die von der Session im traditionellen Betrieb verwendet werden; wenn das Objekt das Attribut InstanceState.key gesetzt hat, wird angenommen, dass das Objekt „detached“ ist und führt zu einem UPDATE. Andernfalls wird ein INSERT verwendet.

    Im Fall eines UPDATE werden Anweisungen basierend darauf gruppiert, welche Attribute sich geändert haben und somit zum Gegenstand jeder SET-Klausel werden. Wenn update_changed_only False ist, werden alle vorhandenen Attribute in die UPDATE-Anweisung übernommen, was dazu beitragen kann, dass die Anweisungen zu einer größeren executemany() gruppiert werden können und den Overhead der Überprüfung des Verlaufs von Attributen reduziert.

  • return_defaults – wenn True, werden Zeilen, bei denen Werte fehlen, die Standardwerte generieren, insbesondere Integer-Primärschlüssel-Standardwerte und Sequenzen, **einzeln** eingefügt, damit der Primärschlüsselwert verfügbar ist. Insbesondere ermöglicht dies, dass Joined-Inheritance und andere Multi-Table-Mappings korrekt eingefügt werden können, ohne dass Primärschlüsselwerte im Voraus angegeben werden müssen; Session.bulk_save_objects.return_defaults **reduziert die Leistungssteigerung** der Methode erheblich. Es wird dringend empfohlen, stattdessen den Standardansatz Session.add_all() zu verwenden.

  • update_changed_only – wenn True, werden UPDATE-Anweisungen basierend auf den Attributen in jedem Zustand gerendert, die Änderungen protokolliert haben. Wenn False, werden alle vorhandenen Attribute in die SET-Klausel aufgenommen, mit Ausnahme von Primärschlüsselattributen.

  • preserve_order – wenn True, entspricht die Reihenfolge von Einfügungen und Aktualisierungen genau der Reihenfolge, in der die Objekte übergeben werden. Wenn False, werden gängige Objekttypen in Einfügungen und Aktualisierungen gruppiert, um mehr Stapelungsmöglichkeiten zu ermöglichen.

method sqlalchemy.orm.scoped_session.bulk_update_mappings(mapper: Mapper[Any], mappings: Iterable[Dict[str, Any]]) None

Führt ein Massen-UPDATE der gegebenen Liste von Mapping-Wörterbüchern durch.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Legacy-Funktion

Diese Methode ist eine Legacy-Funktion ab der 2.0-Serie von SQLAlchemy. Für moderne Massen-INSERT und UPDATE siehe die Abschnitte ORM Massen-INSERT-Anweisungen und ORM Massen-UPDATE nach Primärschlüssel. Die 2.0-API teilt Implementierungsdetails mit dieser Methode und fügt neue Funktionen hinzu.

Parameter:
  • mapper – eine gemappte Klasse oder das eigentliche Mapper-Objekt, das die einzige Art von Objekt repräsentiert, die in der Mapping-Liste enthalten ist.

  • mappings – eine Sequenz von Wörterbüchern, die jeweils den Zustand der abzubildenden Zeile enthalten, die aktualisiert werden soll, in Bezug auf die Attributnamen der abgebildeten Klasse. Wenn das Mapping mehrere Tabellen referenziert, wie z. B. ein Joined-Inheritance-Mapping, kann jedes Wörterbuch Schlüssel enthalten, die für alle Tabellen gelten. Alle Schlüssel, die vorhanden sind und nicht Teil des Primärschlüssels sind, werden in die SET-Klausel der UPDATE-Anweisung übernommen; die erforderlichen Primärschlüsselwerte werden in die WHERE-Klausel übernommen.

method sqlalchemy.orm.scoped_session.close() None

Schließt die transaktionalen Ressourcen und ORM-Objekte, die von dieser Session verwendet werden.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Dies expunged alle ORM-Objekte, die mit dieser Session verbunden sind, beendet jede laufende Transaktion und gibt alle Connection-Objekte frei, die diese Session selbst von zugehörigen Engine-Objekten ausgecheckt hat. Der Vorgang hinterlässt die Session in einem Zustand, in dem sie wieder verwendet werden kann.

Tipp

Im Standard-Ausführungsmodus **verhindert** die Methode Session.close() **nicht sofort die weitere Verwendung der Session**. Die Session selbst hat keinen eindeutig „geschlossenen“ Zustand; sie bedeutet lediglich, dass die Session alle Datenbankverbindungen und ORM-Objekte freigibt.

Das Setzen des Parameters Session.close_resets_only auf False macht den close stattdessen endgültig, sodass jede weitere Aktion an der Session verboten ist.

Geändert in Version 1.4: Die Methode Session.close() erstellt nicht sofort ein neues SessionTransaction-Objekt; stattdessen wird das neue SessionTransaction nur dann erstellt, wenn die Session erneut für eine Datenbankoperation verwendet wird.

Siehe auch

Schließen - Details zu den Semantiken von Session.close() und Session.reset().

Session.reset() - eine ähnliche Methode, die sich wie close() mit dem Parameter Session.close_resets_only auf True verhält.

classmethod sqlalchemy.orm.scoped_session.close_all() None

Schließt *alle* Sessions im Speicher.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Veraltet seit Version 1.3: Die Methode Session.close_all() ist veraltet und wird in einer zukünftigen Version entfernt. Bitte beziehen Sie sich auf close_all_sessions().

method sqlalchemy.orm.scoped_session.commit() None

Leert ausstehende Änderungen und committet die aktuelle Transaktion.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Nach Abschluss des COMMIT-Vorgangs sind alle Objekte vollständig abgelaufen, ihre internen Inhalte werden gelöscht, und sie werden bei der nächsten Zugriffsoperation automatisch neu geladen. In der Zwischenzeit befinden sich diese Objekte in einem abgelaufenen Zustand und funktionieren nicht, wenn sie von der Session detached sind. Außerdem wird diese Neuladeoperation nicht unterstützt, wenn asynchrone APIs verwendet werden. Der Parameter Session.expire_on_commit kann verwendet werden, um dieses Verhalten zu deaktivieren.

Wenn für die Session keine Transaktion vorhanden ist, was bedeutet, dass seit dem letzten Aufruf von Session.commit() keine Operationen auf dieser Session aufgerufen wurden, beginnt die Methode eine interne „logische“ Transaktion und committet sie. Diese beeinträchtigt die Datenbank normalerweise nicht, es sei denn, es wurden ausstehende Flush-Änderungen erkannt, sie löst jedoch Ereignishandler und Regeln für die Objektverlängerung aus.

Die äußerste Datenbanktransaktion wird bedingungslos committet und gibt automatisch alle aktiven SAVEPOINTs frei.

Methode sqlalchemy.orm.scoped_session.configure(**kwargs: Any) None

Konfigurieren Sie die von dieser scoped_session verwendete sessionmaker neu.

Siehe sessionmaker.configure().

Methode sqlalchemy.orm.scoped_session.connection(bind_arguments: _BindArguments | None = None, execution_options: CoreExecuteOptionsParameter | None = None) Connection

Gibt ein Connection-Objekt zurück, das dem transaktionalen Zustand dieses Session-Objekts entspricht.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Entweder wird die Connection, die der aktuellen Transaktion entspricht, zurückgegeben, oder wenn keine Transaktion aktiv ist, wird eine neue begonnen und die zurückgegebene Connection zurückgegeben (beachten Sie, dass bis zur ersten SQL-Anweisung kein transaktionaler Zustand mit der DBAPI hergestellt wird).

Mehrdeutigkeiten bei Multi-Bind- oder ungebundenen Session-Objekten können durch beliebige der optionalen Schlüsselwortargumente aufgelöst werden. Dies führt letztendlich zur Verwendung der get_bind()-Methode zur Auflösung.

Parameter:
Methode sqlalchemy.orm.scoped_session.delete(instance: object) None

Markiert eine Instanz als gelöscht.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Das Objekt wird als persistent oder detached angenommen, wenn es übergeben wird; nach dem Aufruf der Methode bleibt das Objekt im persistent Zustand, bis der nächste Flush erfolgt. Während dieser Zeit wird das Objekt auch Mitglied der Session.deleted-Sammlung sein.

Wenn der nächste Flush erfolgt, wechselt das Objekt in den deleted-Zustand, was anzeigt, dass eine `DELETE`-Anweisung für seine Zeile innerhalb der aktuellen Transaktion ausgegeben wurde. Wenn die Transaktion erfolgreich committet wird, wechselt das gelöschte Objekt in den detached-Zustand und ist nicht mehr in dieser Session vorhanden.

Attribut sqlalchemy.orm.scoped_session.deleted

Die Menge aller Instanzen, die in dieser Session als „gelöscht“ markiert sind.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Attribut sqlalchemy.orm.scoped_session.dirty

Die Menge aller persistenten Instanzen, die als schmutzig gelten.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Z. B.

some_mapped_object in session.dirty

Instanzen gelten als schmutzig, wenn sie modifiziert, aber nicht gelöscht wurden.

Beachten Sie, dass diese „schmutzige“ Berechnung „optimistisch“ ist; die meisten Attributsetz- oder Sammlungsmodifikationsoperationen markieren eine Instanz als „schmutzig“ und platzieren sie in dieser Menge, auch wenn keine Nettoänderung am Attributwert vorliegt. Beim Flush wird der Wert jedes Attributs mit seinem zuvor gespeicherten Wert verglichen, und wenn keine Nettoänderung vorliegt, wird keine SQL-Operation durchgeführt (dies ist eine aufwändigere Operation, daher wird sie nur beim Flush durchgeführt).

Um zu überprüfen, ob eine Instanz wirksame Nettoänderungen an ihren Attributen aufweist, verwenden Sie die Methode Session.is_modified().

Methode sqlalchemy.orm.scoped_session.execute(statement: Executable, params: _CoreAnyExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, _parent_execute_state: Any | None = None, _add_event: Any | None = None) Result[Any]

Führt ein SQL-Ausdruckskonstrukt aus.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Gibt ein Result-Objekt zurück, das die Ergebnisse der Anweisungsausführung darstellt.

Z. B.

from sqlalchemy import select

result = session.execute(select(User).where(User.id == 5))

Die API-Vertrags von Session.execute() ähnelt der von Connection.execute(), der 2.0-Stil von Connection.

Geändert in Version 1.4: Die Methode Session.execute() ist nun der primäre Punkt für die ORM-Anweisungsausführung bei der Verwendung des 2.0-Stils in der ORM-Nutzung.

Parameter:
  • statement – Eine ausführbare Anweisung (d. h. ein Executable-Ausdruck wie select()).

  • params – Optionales Wörterbuch oder Liste von Wörterbüchern, das gebundene Parameterwerte enthält. Wenn ein einzelnes Wörterbuch übergeben wird, erfolgt eine Ausführung einer einzelnen Zeile; wenn eine Liste von Wörterbüchern übergeben wird, wird „executemany“ aufgerufen. Die Schlüssel in jedem Wörterbuch müssen mit den Parameternamen in der Anweisung übereinstimmen.

  • execution_options

    Optionales Wörterbuch mit Ausführungsoptionen, die der Anweisungsausführung zugeordnet werden. Dieses Wörterbuch kann eine Teilmenge der Optionen bereitstellen, die von Connection.execution_options() akzeptiert werden, und kann auch zusätzliche Optionen bereitstellen, die nur in einem ORM-Kontext verstanden werden.

    Siehe auch

    ORM-Ausführungsoptionen - ORM-spezifische Ausführungsoptionen

  • bind_arguments – Wörterbuch mit zusätzlichen Argumenten zur Bestimmung des Bindings. Kann „mapper“, „bind“ oder andere benutzerdefinierte Argumente enthalten. Der Inhalt dieses Wörterbuchs wird an die Methode Session.get_bind() übergeben.

Gibt zurück:

Ein Result-Objekt.

Methode sqlalchemy.orm.scoped_session.expire(instance: object, attribute_names: Iterable[str] | None = None) None

Lässt die Attribute einer Instanz verfallen.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Markiert die Attribute einer Instanz als veraltet. Wenn auf ein abgelaufenes Attribut zugegriffen wird, wird eine Abfrage an den aktuellen transaktionalen Kontext des Session-Objekts ausgegeben, um alle abgelaufenen Attribute für die gegebene Instanz zu laden. Beachten Sie, dass eine stark isolierte Transaktion dieselben Werte zurückgibt, die in derselben Transaktion zuvor gelesen wurden, unabhängig von Änderungen im Datenbankzustand außerhalb dieser Transaktion.

Um alle Objekte in der Session gleichzeitig ablaufen zu lassen, verwenden Sie Session.expire_all().

Das Standardverhalten des Session-Objekts ist es, alle Zustände abzulaufen, wenn die Methoden Session.rollback() oder Session.commit() aufgerufen werden, damit neue Zustände für die neue Transaktion geladen werden können. Aus diesem Grund ist der Aufruf von Session.expire() nur in dem spezifischen Fall sinnvoll, dass in der aktuellen Transaktion eine Nicht-ORM-SQL-Anweisung ausgegeben wurde.

Parameter:
  • instance – Die zu aktualisierende Instanz.

  • attribute_names – Optionale Liste von Zeichenketten-Attributnamen, die eine Teilmenge der ablaufenden Attribute angeben.

Methode sqlalchemy.orm.scoped_session.expire_all() None

Lässt alle persistenten Instanzen innerhalb dieser Session verfallen.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Wenn auf ein beliebiges Attribut einer persistenten Instanz zugegriffen wird, wird eine Abfrage mit dem aktuellen transaktionalen Kontext des Session-Objekts ausgegeben, um alle abgelaufenen Attribute für die gegebene Instanz zu laden. Beachten Sie, dass eine stark isolierte Transaktion dieselben Werte zurückgibt, die in derselben Transaktion zuvor gelesen wurden, unabhängig von Änderungen im Datenbankzustand außerhalb dieser Transaktion.

Um einzelne Objekte und einzelne Attribute auf diesen Objekten ablaufen zu lassen, verwenden Sie Session.expire().

Das Standardverhalten des Session-Objekts ist es, alle Zustände abzulaufen, wenn die Methoden Session.rollback() oder Session.commit() aufgerufen werden, damit neue Zustände für die neue Transaktion geladen werden können. Aus diesem Grund ist der Aufruf von Session.expire_all() normalerweise nicht erforderlich, vorausgesetzt, die Transaktion ist isoliert.

Methode sqlalchemy.orm.scoped_session.expunge(instance: object) None

Entfernt die instance aus dieser Session.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Dies gibt alle internen Referenzen auf die Instanz frei. Kaskadierung wird gemäß der *expunge*-Kaskadenregel angewendet.

Methode sqlalchemy.orm.scoped_session.expunge_all() None

Entfernt alle Objektinstanzen aus dieser Session.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Dies entspricht dem Aufruf von expunge(obj) für alle Objekte in dieser Session.

Methode sqlalchemy.orm.scoped_session.flush(objects: Sequence[Any] | None = None) None

Flush aller Objektänderungen an die Datenbank.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Schreibt alle ausstehenden Objekterstellungen, -löschungen und -änderungen als INSERTs, DELETEs, UPDATEs usw. in die Datenbank. Operationen werden automatisch vom Abhängigkeits-Solver der Session geordnet.

Datenbankoperationen werden im aktuellen Transaktionskontext ausgeführt und wirken sich nicht auf den Zustand der Transaktion aus, es sei denn, es tritt ein Fehler auf, in welchem Fall die gesamte Transaktion zurückgerollt wird. Sie können flush() beliebig oft innerhalb einer Transaktion aufrufen, um Änderungen von Python in den Transaktionspuffer der Datenbank zu verschieben.

Parameter:

objects

Optional; beschränkt die Flush-Operation auf Elemente, die sich in der angegebenen Sammlung befinden.

Diese Funktion ist für sehr spezifische Anwendungsfälle gedacht, bei denen bestimmte Objekte vor dem vollständigen Flush() bearbeitet werden müssen. Sie ist nicht für den allgemeinen Gebrauch bestimmt.

Methode sqlalchemy.orm.scoped_session.get(entity: _EntityBindKey[_O], ident: _PKIdentityArgument, *, options: Sequence[ORMOption] | None = None, populate_existing: bool = False, with_for_update: ForUpdateParameter = None, identity_token: Any | None = None, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None) _O | None

Gibt eine Instanz basierend auf der angegebenen Primärschlüssel-ID zurück, oder None, wenn sie nicht gefunden wurde.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Z. B.

my_user = session.get(User, 5)

some_object = session.get(VersionedFoo, (5, 10))

some_object = session.get(VersionedFoo, {"id": 5, "version_id": 10})

Neu in Version 1.4: Session.get() hinzugefügt, das aus der jetzt veralteten Methode Query.get() verschoben wurde.

Session.get() ist besonders, da es direkten Zugriff auf die Identitätszuordnung der Session bietet. Wenn die angegebene Primärschlüsselkennung in der lokalen Identitätszuordnung vorhanden ist, wird das Objekt direkt aus dieser Sammlung zurückgegeben und keine SQL-Anweisung ausgegeben, es sei denn, das Objekt wurde als vollständig abgelaufen markiert. Wenn es nicht vorhanden ist, wird eine SELECT-Anweisung ausgeführt, um das Objekt zu finden.

Session.get() führt auch eine Prüfung durch, ob das Objekt in der Identitätszuordnung vorhanden und als abgelaufen markiert ist. Eine SELECT-Anweisung wird ausgegeben, um das Objekt zu aktualisieren und sicherzustellen, dass die Zeile noch vorhanden ist. Andernfalls wird ObjectDeletedError ausgelöst.

Parameter:
  • entity – Eine gemappte Klasse oder ein Mapper, die den Typ der zu ladenden Entität angibt.

  • ident

    Ein Skalar, Tupel oder Wörterbuch, das den Primärschlüssel darstellt. Für einen zusammengesetzten (z. B. mehrspaltigen) Primärschlüssel sollte ein Tupel oder Wörterbuch übergeben werden.

    Für einen einspaltigen Primärschlüssel ist die skalare Aufrufform in der Regel die praktikabelste. Wenn der Primärschlüssel einer Zeile der Wert „5“ ist, sieht der Aufruf wie folgt aus

    my_object = session.get(SomeClass, 5)

    Das Tupelformat enthält Primärschlüsselwerte, typischerweise in der Reihenfolge, in der sie den Spalten des zugeordneten Table-Objekts entsprechen, oder wenn der Parameter Mapper.primary_key verwendet wurde, in der für diesen Parameter verwendeten Reihenfolge. Wenn beispielsweise der Primärschlüssel einer Zeile durch die Ganzzahlen „5, 10“ dargestellt wird, würde der Aufruf so aussehen

    my_object = session.get(SomeClass, (5, 10))

    Die Wörterbuchform sollte als Schlüssel die zugeordneten Attributnamen enthalten, die jedem Element des Primärschlüssels entsprechen. Wenn die zugeordnete Klasse die Attribute id und version_id als Attribute hat, die den Primärschlüsselwert des Objekts speichern, sähe der Aufruf wie folgt aus

    my_object = session.get(SomeClass, {"id": 5, "version_id": 10})

  • options – Optionale Sequenz von Ladeoptionen, die auf die Abfrage angewendet werden, falls eine ausgegeben wird.

  • populate_existing – bewirkt, dass die Methode bedingungslos eine SQL-Abfrage ausgibt und das Objekt mit den neu geladenen Daten aktualisiert, unabhängig davon, ob das Objekt bereits vorhanden ist oder nicht.

  • with_for_update – optional boolean True, das angibt, dass FOR UPDATE verwendet werden soll, oder ein Dictionary mit Flags, das eine spezifischere Menge von FOR UPDATE-Flags für das SELECT angibt; die Flags sollten mit den Parametern von Query.with_for_update() übereinstimmen. Überschreibt den Parameter Session.refresh.lockmode.

  • execution_options

    optionales Dictionary von Ausführungsoptionen, die mit der Abfrageausführung verknüpft werden, wenn eine solche emittiert wird. Dieses Dictionary kann eine Teilmenge der Optionen bereitstellen, die von Connection.execution_options() akzeptiert werden, und kann auch zusätzliche Optionen bereitstellen, die nur in einem ORM-Kontext verstanden werden.

    Neu in Version 1.4.29.

    Siehe auch

    ORM-Ausführungsoptionen - ORM-spezifische Ausführungsoptionen

  • bind_arguments

    Dictionary zusätzlicher Argumente zur Bestimmung des Bindings. Kann „mapper“, „bind“ oder andere benutzerdefinierte Argumente enthalten. Der Inhalt dieses Dictionaries wird an die Methode Session.get_bind() übergeben.

Gibt zurück:

Die Objektinstanz oder None.

methode sqlalchemy.orm.scoped_session.get_bind(mapper: _EntityBindKey[_O] | None = None, *, clause: ClauseElement | None = None, bind: _SessionBind | None = None, _sa_skip_events: bool | None = None, _sa_skip_for_implicit_returning: bool = False, **kw: Any) Engine | Connection

Gibt ein „Bind“, an das diese Session gebunden ist, zurück.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Das „Bind“ ist normalerweise eine Instanz von Engine, außer in dem Fall, dass die Session explizit direkt an eine Connection gebunden wurde.

Für eine mehrfach gebundene oder ungebundene Session werden die Argumente mapper oder clause verwendet, um das passende Bind zu bestimmen, das zurückgegeben werden soll.

Beachten Sie, dass das Argument „mapper“ normalerweise vorhanden ist, wenn Session.get_bind() über eine ORM-Operation wie Session.query(), jede einzelne INSERT/UPDATE/DELETE-Operation innerhalb eines Session.flush()-Aufrufs usw. aufgerufen wird.

Die Reihenfolge der Auflösung ist

  1. Wenn ein Mapper angegeben ist und Session.binds vorhanden ist, wird ein Bind basierend zuerst auf dem verwendeten Mapper, dann auf der verwendeten zugeordneten Klasse, dann auf allen Basisklassen, die im __mro__ der zugeordneten Klasse vorhanden sind, von spezifischeren zu allgemeineren Oberklassen gesucht.

  2. Wenn eine Klausel angegeben ist und Session.binds vorhanden ist, wird ein Bind basierend auf Table-Objekten gesucht, die in der angegebenen Klausel vorhanden und in Session.binds enthalten sind.

  3. Wenn Session.binds vorhanden ist, geben Sie diese zurück.

  4. Wenn eine Klausel angegeben ist, wird versucht, ein Bind zurückzugeben, das mit den Metadaten verknüpft ist, die letztendlich mit der Klausel verknüpft sind.

  5. Wenn ein Mapper angegeben ist, wird versucht, ein Bind zurückzugeben, das mit den Metadaten verknüpft ist, die letztendlich mit der Table oder einem anderen wählbaren Element verknüpft sind, auf das der Mapper abgebildet ist.

  6. Wenn kein Bind gefunden werden kann, wird sqlalchemy.exc.UnboundExecutionError ausgelöst.

Beachten Sie, dass die Methode Session.get_bind() in einer benutzerdefinierten Unterklasse von Session überschrieben werden kann, um jede Art von Bind-Auflösungsschema bereitzustellen. Sehen Sie das Beispiel unter Benutzerdefinierte vertikale Partitionierung.

Parameter:
  • mapper – Optionale zugeordnete Klasse oder entsprechende Mapper-Instanz. Das Bind kann von einem Mapper abgeleitet werden, indem zuerst die „binds“-Map konsultiert wird, die dieser Session zugeordnet ist, und zweitens die Metadaten, die der Table zugeordnet sind, auf die der Mapper abgebildet ist, für ein Bind konsultiert wird.

  • clause – Ein ClauseElement (d. h. select(), text() usw.). Wenn das Argument mapper nicht vorhanden ist oder kein Bind ergeben konnte, wird der gegebene Ausdruckskonstrukt nach einem gebundenen Element durchsucht, typischerweise einer Table, die mit gebundenen Metadaten verknüpft ist.

methode sqlalchemy.orm.scoped_session.get_one(entity: _EntityBindKey[_O], ident: _PKIdentityArgument, *, options: Sequence[ORMOption] | None = None, populate_existing: bool = False, with_for_update: ForUpdateParameter = None, identity_token: Any | None = None, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None) _O

Gibt genau eine Instanz basierend auf dem gegebenen Primärschlüssel-Identifikator zurück oder löst eine Ausnahme aus, wenn sie nicht gefunden wird.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Löst sqlalchemy.orm.exc.NoResultFound aus, wenn die Abfrage keine Zeilen auswählt.

Für eine detaillierte Dokumentation der Argumente siehe die Methode Session.get().

Neu in Version 2.0.22.

Gibt zurück:

Die Objektinstanz.

Siehe auch

Session.get() - äquivalente Methode, die stattdessen

gibt None zurück, wenn keine Zeile mit dem angegebenen Primärschlüssel gefunden wurde

classmethod sqlalchemy.orm.scoped_session.identity_key(class_: Type[Any] | None = None, ident: Any | Tuple[Any, ...] = None, *, instance: Any | None = None, row: Row[Any] | RowMapping | None = None, identity_token: Any | None = None) _IdentityKeyType[Any]

Gibt einen Identitätsschlüssel zurück.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Dies ist ein Alias für identity_key().

attribut sqlalchemy.orm.scoped_session.identity_map

Proxy für das Attribut Session.identity_map im Namen der Klasse scoped_session.

attribut sqlalchemy.orm.scoped_session.info

Ein benutzerdefinierbares Dictionary.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Der Anfangswert dieses Dictionaries kann mithilfe des Arguments info für den Konstruktor der Session oder den Konstruktor und die Factory-Methoden von sessionmaker gefüllt werden. Das Dictionary ist hier immer lokal für diese Session und kann unabhängig von allen anderen Session-Objekten geändert werden.

attribut sqlalchemy.orm.scoped_session.is_active

True, wenn diese Session sich nicht im Zustand „partielles Rollback“ befindet.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Geändert in Version 1.4: Die Session startet keine Transaktion mehr sofort, daher ist dieses Attribut False, wenn die Session zum ersten Mal instanziiert wird.

Der Zustand „partielles Rollback“ zeigt typischerweise an, dass der Flush-Prozess der Session fehlgeschlagen ist und dass die Methode Session.rollback() aufgerufen werden muss, um die Transaktion vollständig zurückzurollen.

Wenn diese Session überhaupt nicht in einer Transaktion ist, beginnt die Session beim ersten Gebrauch automatisch, sodass in diesem Fall Session.is_active True zurückgibt.

Andernfalls, wenn sich diese Session innerhalb einer Transaktion befindet und diese Transaktion intern nicht zurückgerollt wurde, gibt Session.is_active ebenfalls True zurück.

methode sqlalchemy.orm.scoped_session.is_modified(instance: object, include_collections: bool = True) bool

Gibt True zurück, wenn die gegebene Instanz lokal geänderte Attribute hat.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Diese Methode ruft die Historie für jedes instrumentierte Attribut der Instanz ab und vergleicht den aktuellen Wert mit seinem zuvor geleerten oder committeten Wert, falls vorhanden.

Sie ist im Wesentlichen eine teurere und genauere Version der Überprüfung der Instanz in der Sammlung Session.dirty; es wird ein vollständiger Test für den Netto-„dirty“-Status jedes Attributs durchgeführt.

Z. B.

return session.is_modified(someobject)

Einige Vorbehalte zu dieser Methode gelten:

  • Instanzen, die in der Sammlung Session.dirty vorhanden sind, können bei der Überprüfung mit dieser Methode False zurückgeben. Dies liegt daran, dass das Objekt möglicherweise Änderungsereignisse durch Attributmutationen erhalten hat, wodurch es in Session.dirty aufgenommen wurde, aber letztendlich ist der Zustand derselbe wie der aus der Datenbank geladene, was hier zu keiner Nettobewegung führt.

  • Skalare Attribute haben möglicherweise nicht den zuvor gesetzten Wert aufgezeichnet, wenn ein neuer Wert angewendet wurde, falls das Attribut zum Zeitpunkt des Empfangs des neuen Wertes nicht geladen war oder abgelaufen war. In diesen Fällen wird angenommen, dass das Attribut eine Änderung erfahren hat, auch wenn es letztendlich keine Nettobewegung gegenüber seinem Datenbankwert gibt. SQLAlchemy benötigt in den meisten Fällen nicht den „alten“ Wert, wenn ein Set-Ereignis auftritt, und überspringt daher die Kosten eines SQL-Aufrufs, wenn der alte Wert nicht vorhanden ist, basierend auf der Annahme, dass ein UPDATE des skalaren Werts normalerweise erforderlich ist und in den wenigen Fällen, in denen dies nicht der Fall ist, im Durchschnitt weniger kostspielig ist als die Ausgabe eines defensiven SELECTs.

    Der „alte“ Wert wird bedingungslos beim Setzen abgerufen, nur wenn der Attributcontainer das Flag active_history auf True gesetzt hat. Dieses Flag wird typischerweise für Primärschlüsselattribute und skalare Objektverweise gesetzt, die keine einfachen Many-to-One-Beziehungen sind. Um dieses Flag für jede beliebige zugeordnete Spalte zu setzen, verwenden Sie das Argument active_history mit column_property().

Parameter:
  • instance – Die zu prüfende zugeordnete Instanz auf ausstehende Änderungen.

  • include_collections – Gibt an, ob mehrwertige Sammlungen in die Operation einbezogen werden sollen. Das Setzen dieses Werts auf False ist eine Möglichkeit, nur spaltenbasierte lokale Eigenschaften zu erkennen (d. h. skalare Spalten oder Many-to-One-Fremdschlüssel), die bei einem Flush zu einem UPDATE für diese Instanz führen würden.

methode sqlalchemy.orm.scoped_session.merge(instance: _O, *, load: bool = True, options: Sequence[ORMOption] | None = None) _O

Kopiert den Zustand einer gegebenen Instanz in eine entsprechende Instanz innerhalb dieser Session.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Session.merge() untersucht die Primärschlüsselattribute der Quellinstanz und versucht, sie mit einer Instanz desselben Primärschlüssels in der Sitzung abzugleichen. Wenn sie lokal nicht gefunden wird, versucht sie, das Objekt anhand des Primärschlüssels aus der Datenbank zu laden, und wenn keines gefunden werden kann, erstellt sie eine neue Instanz. Der Zustand jedes Attributs der Quellinstanz wird dann in die Zielinstanz kopiert. Die resultierende Zielinstanz wird dann von der Methode zurückgegeben; die ursprüngliche Quellinstanz bleibt unverändert und nicht mit der Session verknüpft, falls sie es nicht bereits war.

Diese Operation wird auf zugeordnete Instanzen übertragen, wenn die Zuordnung mit cascade="merge" zugeordnet ist.

Siehe Merging für eine detaillierte Erörterung des Mergings.

Parameter:
  • instance – Zu mergendes Objekt.

  • load

    Boolean, wenn False, wechselt merge() in einen "Hochleistungsmodus", der dazu führt, dass keine Verlaufereignisse und kein Datenbankzugriff emittiert werden. Dieses Flag wird für Fälle wie die Übertragung von Objektdiagrammen in eine Session aus einem Second-Level-Cache oder die Übertragung gerade geladener Objekte in die von einem Worker-Thread oder -Prozess besessene Session ohne erneutes Abfragen der Datenbank verwendet.

    Der Anwendungsfall load=False fügt die Einschränkung hinzu, dass das gegebene Objekt sich in einem "sauberen" Zustand befinden muss, d. h. keine ausstehenden Änderungen zum Flushen hat – auch wenn das eingehende Objekt von jeder Session getrennt ist. Dies geschieht, damit beim Mergen, das lokale Attribute und verwandte Objekte und Sammlungen füllt, die Werte unverändert auf das Zielobjekt "gestempelt" werden können, ohne Ereignisse zu generieren, und ohne die eingehenden Daten mit vorhandenen verwandten Objekten oder Sammlungen abgleichen zu müssen, die möglicherweise nicht geladen wurden. Die resultierenden Objekte aus load=False werden immer als "sauber" erzeugt, daher ist es nur angemessen, dass die gegebenen Objekte ebenfalls "sauber" sind, andernfalls deutet dies auf eine falsche Verwendung der Methode hin.

  • options

    optionale Sequenz von Ladeoptionen, die auf die Session.get() Methode angewendet werden, wenn die Merge-Operation die existierende Version des Objekts aus der Datenbank lädt.

    Neu in Version 1.4.24.

Siehe auch

make_transient_to_detached() - bietet eine alternative Möglichkeit, ein einzelnes Objekt in die Session zu "mergen"

attribute sqlalchemy.orm.scoped_session.new

Die Menge aller Instanzen, die in dieser Session als 'new' markiert sind.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

attribute sqlalchemy.orm.scoped_session.no_autoflush

Gibt einen Kontextmanager zurück, der Autoflush deaktiviert.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

z. B.

with session.no_autoflush:

    some_object = SomeClass()
    session.add(some_object)
    # won't autoflush
    some_object.related_thing = session.query(SomeRelated).first()

Operationen, die innerhalb des with: Blocks ausgeführt werden, unterliegen keinen Flushes, die beim Zugriff auf Abfragen erfolgen. Dies ist nützlich, wenn eine Reihe von Objekten initialisiert wird, die bestehende Datenbankabfragen beinhalten, wobei das unvollständige Objekt noch nicht geflusht werden soll.

classmethod sqlalchemy.orm.scoped_session.object_session(instance: object) Session | None

Gibt die Session zurück, zu der ein Objekt gehört.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Dies ist ein Alias für object_session().

method sqlalchemy.orm.scoped_session.query(*entities: _ColumnsClauseArgument[Any], **kwargs: Any) Query[Any]

Gibt ein neues Query-Objekt zurück, das zu dieser Session gehört.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Beachten Sie, dass das Query-Objekt ab SQLAlchemy 2.0 veraltet ist; die select()-Konstruktion wird jetzt verwendet, um ORM-Abfragen zu erstellen.

Siehe auch

SQLAlchemy Unified Tutorial

ORM Abfragehandbuch

Legacy Query API - Dokumentation der veralteten API

method sqlalchemy.orm.scoped_session.query_property(query_cls: Type[Query[_T]] | None = None) QueryPropertyDescriptor

Gibt eine Klassen-Eigenschaft zurück, die ein veraltetes Query-Objekt gegen die Klasse und die aktuelle Session zurückgibt, wenn sie aufgerufen wird.

Legacy-Funktion

Der Accessor scoped_session.query_property() ist spezifisch für das veraltete Query-Objekt und gilt nicht als Teil der ORM-Verwendung im 2.0-Stil.

z. B.

from sqlalchemy.orm import QueryPropertyDescriptor
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker

Session = scoped_session(sessionmaker())


class MyClass:
    query: QueryPropertyDescriptor = Session.query_property()


# after mappers are defined
result = MyClass.query.filter(MyClass.name == "foo").all()

Gibt standardmäßig Instanzen der konfigurierten Query-Klasse der Session zurück. Um dies zu überschreiben und eine benutzerdefinierte Implementierung zu verwenden, stellen Sie einen aufrufbaren query_cls bereit. Der Aufrufbare wird mit der Mapper-Klasse als positionales Argument und einer Session als Schlüsselwortargument aufgerufen.

Es gibt keine Begrenzung für die Anzahl der Query-Eigenschaften, die einer Klasse zugewiesen werden können.

method sqlalchemy.orm.scoped_session.refresh(instance: object, attribute_names: Iterable[str] | None = None, with_for_update: ForUpdateParameter = None) None

Attribute auf der gegebenen Instanz ablaufen lassen und aktualisieren.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Die ausgewählten Attribute werden zuerst abgelaufen, wie beim Verwenden von Session.expire(); dann wird eine SELECT-Anweisung an die Datenbank ausgegeben, um spaltenorientierte Attribute mit dem aktuellen Wert im aktuellen Transaktionskontext zu aktualisieren.

relationship()-orientierte Attribute werden ebenfalls sofort geladen, wenn sie bereits auf dem Objekt eager geladen wurden, unter Verwendung derselben Eager-Loading-Strategie, mit der sie ursprünglich geladen wurden.

Neu in Version 1.4: - die Methode Session.refresh() kann auch eager geladene Attribute aktualisieren.

relationship()-orientierte Attribute, die normalerweise mit der select (oder "lazy") Loader-Strategie geladen würden, werden ebenfalls geladen, **wenn sie explizit in der Attributsammlung attribute_names aufgeführt sind**, wobei eine SELECT-Anweisung für das Attribut mit der immediate-Loader-Strategie ausgegeben wird. Wenn Lazy-Loaded-Beziehungen nicht in Session.refresh.attribute_names genannt werden, bleiben sie als "lazy loaded" Attribute erhalten und werden nicht implizit aktualisiert.

Geändert in Version 2.0.4: Die Methode Session.refresh() wird nun Lazy-Loaded-Attribute, die relationship()-orientiert sind, für diejenigen aktualisieren, die explizit in der Attributsammlung Session.refresh.attribute_names aufgeführt sind.

Tipp

Während die Methode Session.refresh() sowohl spalten- als auch beziehungsorientierte Attribute aktualisieren kann, liegt ihr Hauptaugenmerk auf der Aktualisierung lokaler, spaltenorientierter Attribute einer einzelnen Instanz. Für umfangreichere "Refresh"-Funktionalitäten, einschließlich der Möglichkeit, Attribute auf vielen Objekten gleichzeitig zu aktualisieren und explizite Kontrolle über Relationship-Loader-Strategien zu haben, verwenden Sie stattdessen die Funktion populate existing.

Beachten Sie, dass eine stark isolierte Transaktion dieselben Werte zurückgibt, die bereits in derselben Transaktion gelesen wurden, unabhängig von Änderungen im Datenbankzustand außerhalb dieser Transaktion. Das Aktualisieren von Attributen ist normalerweise nur zu Beginn einer Transaktion sinnvoll, in der die Datenbankzeilen noch nicht abgerufen wurden.

Parameter:
  • attribute_names – optional. Eine iterierbare Sammlung von String-Attributnamen, die eine Untermenge der zu aktualisierenden Attribute angibt.

  • with_for_update – optionales Boolean True, das angibt, dass FOR UPDATE verwendet werden soll, oder ein Wörterbuch mit Flags, das einen spezifischeren Satz von FOR UPDATE-Flags für SELECT angibt; Flags sollten den Parametern von Query.with_for_update() entsprechen. Überschreibt den Parameter Session.refresh.lockmode.

Siehe auch

Aktualisieren / Ablaufen lassen - Einführungsmaterial

Session.expire()

Session.expire_all()

Populate Existing - ermöglicht es jeder ORM-Abfrage, Objekte zu aktualisieren, wie sie normalerweise geladen würden.

method sqlalchemy.orm.scoped_session.remove() None

Verwerfen Sie die aktuelle Session, falls vorhanden.

Dies ruft zuerst die Methode Session.close() der aktuellen Session auf, wodurch alle noch gehaltenen Transaktions-/Verbindungsressourcen freigegeben werden; Transaktionen werden speziell zurückgerollt. Die Session wird dann verworfen. Bei der nächsten Verwendung im selben Gültigkeitsbereich wird die scoped_session ein neues Session-Objekt erzeugen.

method sqlalchemy.orm.scoped_session.reset() None

Schließen Sie die Transaktionsressourcen und ORM-Objekte, die von dieser Session verwendet werden, und setzen Sie die Session auf ihren ursprünglichen Zustand zurück.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Diese Methode bietet das gleiche "Reset-only"-Verhalten wie die Session.close()-Methode historisch geboten hat, bei der der Zustand der Session so zurückgesetzt wird, als wäre das Objekt brandneu und bereit zur erneuten Verwendung. Diese Methode kann daher für Session-Objekte nützlich sein, bei denen Session.close_resets_only auf False gesetzt ist, sodass das "nur zurücksetzen"-Verhalten weiterhin verfügbar ist.

Neu in Version 2.0.22.

Siehe auch

Schließen - Details zu den Semantiken von Session.close() und Session.reset().

Session.close() - eine ähnliche Methode verhindert zusätzlich die Wiederverwendung der Session, wenn der Parameter Session.close_resets_only auf False gesetzt ist.

method sqlalchemy.orm.scoped_session.rollback() None

Die aktuelle laufende Transaktion zurückrollen.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Wenn keine Transaktion läuft, ist diese Methode ein Pass-through.

Die Methode rollt immer die oberste Datenbanktransaktion zurück und verwirft dabei alle möglichen verschachtelten Transaktionen, die gerade laufen.

method sqlalchemy.orm.scoped_session.scalar(statement: Executable, params: _CoreSingleExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) Any

Führt eine Anweisung aus und gibt ein Skalaren-Ergebnis zurück.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Verwendung und Parameter sind die gleichen wie bei Session.execute(); das Rückgabeergebnis ist ein skalarer Python-Wert.

method sqlalchemy.orm.scoped_session.scalars(statement: Executable, params: _CoreAnyExecuteParams | None = None, *, execution_options: OrmExecuteOptionsParameter = {}, bind_arguments: _BindArguments | None = None, **kw: Any) ScalarResult[Any]

Führt eine Anweisung aus und gibt die Ergebnisse als Skalare zurück.

Proxied für die Session-Klasse im Auftrag der scoped_session-Klasse.

Verwendung und Parameter sind die gleichen wie bei Session.execute(); das Rückgabeergebnis ist ein ScalarResult-Filterobjekt, das einzelne Elemente anstelle von Row-Objekten zurückgibt.

Gibt zurück:

ein ScalarResult-Objekt

Neu in Version 1.4.24: Session.scalars() hinzugefügt

Neu in Version 1.4.26: scoped_session.scalars() hinzugefügt

Siehe auch

Auswählen von ORM-Entitäten - stellt das Verhalten von Session.execute() zu Session.scalars() gegenüber.

attribute sqlalchemy.orm.scoped_session.session_factory: sessionmaker[_S]

Die an __init__ übergebene session_factory wird in diesem Attribut gespeichert und kann später abgerufen werden. Dies kann nützlich sein, wenn eine neue, nicht-scoped Session benötigt wird.

class sqlalchemy.util.ScopedRegistry

Eine Registry, die eine oder mehrere Instanzen einer einzelnen Klasse auf Basis einer „scope“-Funktion speichern kann.

Das Objekt implementiert __call__ als "Getter", sodass durch Aufrufen von myregistry() das enthaltene Objekt für den aktuellen Gültigkeitsbereich zurückgegeben wird.

Parameter:
  • createfunc – ein aufrufbares Objekt, das ein neues Objekt zurückgibt, das in der Registrierung platziert werden soll

  • scopefunc – ein aufrufbares Objekt, das einen Schlüssel zum Speichern/Abrufen eines Objekts zurückgibt.

Mitglieder

__init__(), clear(), has(), set()

Klassensignatur

class sqlalchemy.util.ScopedRegistry (typing.Generic)

Methode sqlalchemy.util.ScopedRegistry.__init__(createfunc: Callable[[], _T], scopefunc: Callable[[], Any])

Erstellt eine neue ScopedRegistry.

Parameter:
  • createfunc – Eine Erstellungsfunktion, die einen neuen Wert für den aktuellen Geltungsbereich generiert, falls keiner vorhanden ist.

  • scopefunc – Eine Funktion, die ein hashbares Token zurückgibt, das den aktuellen Geltungsbereich repräsentiert (z. B. die aktuelle Thread-ID).

Methode sqlalchemy.util.ScopedRegistry.clear() None

Löscht den aktuellen Geltungsbereich, falls vorhanden.

Methode sqlalchemy.util.ScopedRegistry.has() bool

Gibt True zurück, wenn ein Objekt im aktuellen Geltungsbereich vorhanden ist.

Methode sqlalchemy.util.ScopedRegistry.set(obj: _T) None

Setzt den Wert für den aktuellen Geltungsbereich.

Klasse sqlalchemy.util.ThreadLocalRegistry

Eine ScopedRegistry, die eine threading.local()-Variable zur Speicherung verwendet.

Klasse sqlalchemy.orm.QueryPropertyDescriptor

Beschreibt den Typ, der auf ein Klassenattribut scoped_session.query_property() angewendet wird.

Neu ab Version 2.0.5.

Klassensignatur

class sqlalchemy.orm.QueryPropertyDescriptor (typing_extensions.Protocol)