SQLAlchemy 2.0 Dokumentation
SQLAlchemy ORM
- ORM Schnellstart
- ORM Abgebildete Klassenkonfiguration
- Beziehungskonfiguration
- ORM Abfragehandbuch
- Verwendung der Sitzung
- Ereignisse und Interna
- ORM Erweiterungen
- Asynchrone E/A (asyncio)
- Assoziationsproxy
- Automap¶
- Grundlegende Verwendung
- Generieren von Abbildungen aus vorhandenen MetaData
- Generieren von Abbildungen aus mehreren Schemas
- Explizites Festlegen von Klassen
- Überschreiben von Benennungsschemata
- Beziehungserkennung
- Verwendung von Automap mit expliziten Deklarationen
- Abfangen von Spaltendefinitionen
- API-Referenz
- Baked Queries
- Deklarative Erweiterungen
- Mypy / Pep-484 Unterstützung für ORM-Mappings
- Mutationsverfolgung
- Sortierungsliste
- Horizontale Sharding
- Hybrid-Attribute
- Indexierbar
- Alternative Klassen-Instrumentierung
- ORM Beispiele
Projektversionen
- Vorheriges: Association Proxy
- Nächstes: Baked Queries
- Oben: Startseite
- Auf dieser Seite
- Automap
- Grundlegende Verwendung
- Generieren von Abbildungen aus vorhandenen MetaData
- Generieren von Abbildungen aus mehreren Schemas
- Explizites Festlegen von Klassen
- Überschreiben von Benennungsschemata
- Beziehungserkennung
- Verwendung von Automap mit expliziten Deklarationen
- Abfangen von Spaltendefinitionen
- API-Referenz
Automap¶
Definiert eine Erweiterung für das sqlalchemy.ext.declarative-System, das automatisch zugeordnete Klassen und Beziehungen aus einem Datenbankschema generiert, typischerweise, aber nicht notwendigerweise, aus einem, das reflektiert wurde.
Es wird gehofft, dass das AutomapBase-System eine schnelle und modernisierte Lösung für das Problem darstellt, das auch das sehr berühmte SQLSoup zu lösen versucht: die schnelle und rudimentäre Generierung eines Objektmodells aus einer bestehenden Datenbank im laufenden Betrieb. Indem das Problem strikt auf der Mapper-Konfigurationsebene angegangen und vollständig in bestehende Declarative-Klassentechniken integriert wird, versucht AutomapBase, einen gut integrierten Ansatz für die Problematik der schnellen automatischen Generierung von Ad-hoc-Abbildungen bereitzustellen.
Tipp
Die Automap-Erweiterung ist auf einen "Zero-Declaration"-Ansatz ausgerichtet, bei dem ein vollständiges ORM-Modell einschließlich Klassen und vordefinierter Beziehungen aus einem Datenbankschema im laufenden Betrieb generiert werden kann. Für Anwendungen, die weiterhin explizite Klassendefinitionen einschließlich expliziter Beziehungsdefinitionen in Verbindung mit der Reflexion von Tabellen verwenden möchten, ist die Klasse DeferredReflection, die unter Verwendung von DeferredReflection beschrieben wird, die bessere Wahl.
Grundlegende Verwendung¶
Die einfachste Verwendung besteht darin, eine bestehende Datenbank in ein neues Modell zu spiegeln. Wir erstellen eine neue AutomapBase-Klasse auf ähnliche Weise, wie wir eine deklarative Basisklasse erstellen, mit automap_base(). Anschließend rufen wir AutomapBase.prepare() auf der resultierenden Basisklasse auf und bitten sie, das Schema zu spiegeln und Abbildungen zu erstellen.
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine
Base = automap_base()
# engine, suppose it has two tables 'user' and 'address' set up
engine = create_engine("sqlite:///mydatabase.db")
# reflect the tables
Base.prepare(autoload_with=engine)
# mapped classes are now created with names by default
# matching that of the table name.
User = Base.classes.user
Address = Base.classes.address
session = Session(engine)
# rudimentary relationships are produced
session.add(Address(email_address="foo@bar.com", user=User(name="foo")))
session.commit()
# collection-based relationships are by default named
# "<classname>_collection"
u1 = session.query(User).first()
print(u1.address_collection)Das Aufrufen von AutomapBase.prepare() im obigen Beispiel mit dem Parameter AutomapBase.prepare.reflect gibt an, dass die Methode MetaData.reflect() für die MetaData-Sammlung dieser deklarativen Basisklassen aufgerufen wird; dann erhält jede gültige Table innerhalb der MetaData automatisch eine neue zugeordnete Klasse. Die ForeignKeyConstraint-Objekte, die die verschiedenen Tabellen miteinander verbinden, werden verwendet, um neue, bidirektionale relationship()-Objekte zwischen den Klassen zu erzeugen. Die Klassen und Beziehungen folgen einem Standardbenennungsschema, das wir anpassen können. An diesem Punkt ist unsere grundlegende Zuordnung, die aus den verwandten Klassen User und Address besteht, bereit für die traditionelle Verwendung.
Hinweis
Mit gültig meinen wir, dass eine Tabelle, um zugeordnet zu werden, einen Primärschlüssel angeben muss. Zusätzlich, wenn die Tabelle als reine Zuordnungstabelle zwischen zwei anderen Tabellen erkannt wird, wird sie nicht direkt zugeordnet, sondern stattdessen als Many-to-Many-Tabelle zwischen den Zuordnungen der beiden referenzierenden Tabellen konfiguriert.
Generieren von Abbildungen aus vorhandenen MetaData¶
Wir können ein bereits deklariertes MetaData-Objekt an automap_base() übergeben. Dieses Objekt kann auf jede Weise konstruiert werden, einschließlich programmgesteuert, aus einer serialisierten Datei oder durch Reflexion mit MetaData.reflect(). Unten illustrieren wir eine Kombination aus Reflexion und expliziter Tabellendeklaration.
from sqlalchemy import create_engine, MetaData, Table, Column, ForeignKey
from sqlalchemy.ext.automap import automap_base
engine = create_engine("sqlite:///mydatabase.db")
# produce our own MetaData object
metadata = MetaData()
# we can reflect it ourselves from a database, using options
# such as 'only' to limit what tables we look at...
metadata.reflect(engine, only=["user", "address"])
# ... or just define our own Table objects with it (or combine both)
Table(
"user_order",
metadata,
Column("id", Integer, primary_key=True),
Column("user_id", ForeignKey("user.id")),
)
# we can then produce a set of mappings from this MetaData.
Base = automap_base(metadata=metadata)
# calling prepare() just sets up mapped classes and relationships.
Base.prepare()
# mapped classes are ready
User = Base.classes.user
Address = Base.classes.address
Order = Base.classes.user_orderGenerieren von Abbildungen aus mehreren Schemas¶
Die Methode AutomapBase.prepare() kann beim Spiegeln Tabellen aus höchstens einem Schema gleichzeitig spiegeln, wobei der Parameter AutomapBase.prepare.schema verwendet wird, um den Namen des zu spiegelnden Schemas anzugeben. Um AutomapBase mit Tabellen aus mehreren Schemas zu füllen, kann AutomapBase.prepare() mehrmals aufgerufen werden, wobei jedes Mal ein anderer Name für den Parameter AutomapBase.prepare.schema übergeben wird. Die Methode AutomapBase.prepare() verwaltet eine interne Liste von Table-Objekten, die bereits zugeordnet wurden, und fügt nur für solche Table-Objekte neue Zuordnungen hinzu, die seit dem letzten Aufruf von AutomapBase.prepare() neu sind.
e = create_engine("postgresql://scott:tiger@localhost/test")
Base.metadata.create_all(e)
Base = automap_base()
Base.prepare(e)
Base.prepare(e, schema="test_schema")
Base.prepare(e, schema="test_schema_2")Neu in Version 2.0: Die Methode AutomapBase.prepare() kann beliebig oft aufgerufen werden; nur neu hinzugefügte Tabellen werden bei jedem Durchlauf zugeordnet. Zuvor in Version 1.4 und früheren Versionen würden mehrfache Aufrufe zu Fehlern führen, da versucht würde, eine bereits zugeordnete Klasse erneut zuzuordnen. Der frühere Workaround-Ansatz, MetaData.reflect() direkt aufzurufen, bleibt ebenfalls verfügbar.
Abbilden von Tabellen mit demselben Namen über mehrere Schemas hinweg¶
Für den gängigen Fall, dass mehrere Schemas Tabellen mit demselben Namen haben und daher Klassen mit demselben Namen generieren würden, können Konflikte entweder durch die Verwendung des Hooks AutomapBase.prepare.classname_for_table zur Anwendung unterschiedlicher Klassennamen pro Schema oder durch die Verwendung des Hooks AutomapBase.prepare.modulename_for_table gelöst werden, der eine Disambiguierung von Klassen mit demselben Namen durch Änderung ihres effektiven __module__-Attributs ermöglicht. Im folgenden Beispiel wird dieser Hook verwendet, um ein __module__-Attribut für alle Klassen zu erstellen, das die Form mymodule.<schemaname> hat, wobei der Schema-Name default verwendet wird, wenn kein Schema vorhanden ist.
e = create_engine("postgresql://scott:tiger@localhost/test")
Base.metadata.create_all(e)
def module_name_for_table(cls, tablename, table):
if table.schema is not None:
return f"mymodule.{table.schema}"
else:
return f"mymodule.default"
Base = automap_base()
Base.prepare(e, modulename_for_table=module_name_for_table)
Base.prepare(
e, schema="test_schema", modulename_for_table=module_name_for_table
)
Base.prepare(
e, schema="test_schema_2", modulename_for_table=module_name_for_table
)Die gleichnamigen Klassen sind in einer hierarchischen Sammlung organisiert, die unter AutomapBase.by_module verfügbar ist. Diese Sammlung wird mit dem punktgetrennten Namen eines bestimmten Pakets/Moduls bis hin zum gewünschten Klassennamen durchlaufen.
Hinweis
Bei Verwendung des Hooks AutomapBase.prepare.modulename_for_table, um einen neuen __module__ zurückzugeben, der nicht None ist, wird die Klasse nicht in die Sammlung AutomapBase.classes aufgenommen; nur Klassen, denen kein expliziter Modulname zugewiesen wurde, werden hier aufgenommen, da die Sammlung gleichnamige Klassen nicht einzeln darstellen kann.
Im obigen Beispiel, wenn die Datenbank eine Tabelle namens accounts in allen drei Schemas (standard, test_schema und test_schema_2) enthielt, werden drei separate Klassen verfügbar sein als:
Base.by_module.mymodule.default.accounts
Base.by_module.mymodule.test_schema.accounts
Base.by_module.mymodule.test_schema_2.accountsDer Standardmodul-Namensraum, der für alle AutomapBase-Klassen generiert wird, ist sqlalchemy.ext.automap. Wenn kein Hook AutomapBase.prepare.modulename_for_table verwendet wird, sind die Inhalte von AutomapBase.by_module vollständig im Namensraum sqlalchemy.ext.automap enthalten (z. B. MyBase.by_module.sqlalchemy.ext.automap.<classname>), was die gleiche Reihe von Klassen enthält wie die, die in AutomapBase.classes zu sehen wären. Daher ist es im Allgemeinen nur notwendig, AutomapBase.by_module zu verwenden, wenn explizite __module__-Konventionen vorhanden sind.
Explizites Festlegen von Klassen¶
Tipp
Wenn explizite Klassen in einer Anwendung eine wichtige Rolle spielen sollen, sollten Sie stattdessen DeferredReflection in Betracht ziehen.
Die Erweiterung automap ermöglicht es, Klassen explizit zu definieren, ähnlich wie bei der Klasse DeferredReflection. Klassen, die von AutomapBase erben, verhalten sich wie normale deklarative Klassen, werden aber nicht sofort nach ihrer Erstellung zugeordnet, sondern erst, wenn wir AutomapBase.prepare() aufrufen. Die Methode AutomapBase.prepare() verwendet die von uns eingerichteten Klassen basierend auf dem verwendeten Tabellennamen. Wenn unser Schema die Tabellen user und address enthält, können wir eine oder beide Klassen definieren, die verwendet werden sollen.
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine
# automap base
Base = automap_base()
# pre-declare User for the 'user' table
class User(Base):
__tablename__ = "user"
# override schema elements like Columns
user_name = Column("name", String)
# override relationships too, if desired.
# we must use the same name that automap would use for the
# relationship, and also must refer to the class name that automap will
# generate for "address"
address_collection = relationship("address", collection_class=set)
# reflect
engine = create_engine("sqlite:///mydatabase.db")
Base.prepare(autoload_with=engine)
# we still have Address generated from the tablename "address",
# but User is the same as Base.classes.User now
Address = Base.classes.address
u1 = session.query(User).first()
print(u1.address_collection)
# the backref is still there:
a1 = session.query(Address).first()
print(a1.user)Eines der komplizierteren Details in dem obigen Beispiel ist, dass wir eines der relationship()-Objekte überschrieben haben, die Automap erstellt hätte. Um dies zu tun, mussten wir sicherstellen, dass die Namen mit dem übereinstimmen, was Automap normalerweise generiert, nämlich dass der Beziehungsname User.address_collection ist und der Name der Klasse, auf die verwiesen wird, aus Sicht von Automap address heißt, auch wenn wir uns mit Address auf diese beziehen, wenn wir diese Klasse verwenden.
Überschreiben von Benennungsschemata¶
Der automap-Erweiterung ist die Aufgabe zugewiesen, zugeordnete Klassen und Beziehungsnamen basierend auf einem Schema zu erstellen, was bedeutet, dass sie Entscheidungspunkte hat, wie diese Namen bestimmt werden. Diese drei Entscheidungspunkte werden über Funktionen bereitgestellt, die an die Methode AutomapBase.prepare() übergeben werden können und als classname_for_table(), name_for_scalar_relationship() und name_for_collection_relationship() bekannt sind. Diese Funktionen können ganz oder teilweise wie im folgenden Beispiel bereitgestellt werden, in dem wir ein "Camel Case"-Schema für Klassennamen und einen "Pluralizer" für Sammlungsnamen unter Verwendung des Pakets Inflect verwenden.
import re
import inflect
def camelize_classname(base, tablename, table):
"Produce a 'camelized' class name, e.g."
"'words_and_underscores' -> 'WordsAndUnderscores'"
return str(
tablename[0].upper()
+ re.sub(
r"_([a-z])",
lambda m: m.group(1).upper(),
tablename[1:],
)
)
_pluralizer = inflect.engine()
def pluralize_collection(base, local_cls, referred_cls, constraint):
"Produce an 'uncamelized', 'pluralized' class name, e.g."
"'SomeTerm' -> 'some_terms'"
referred_name = referred_cls.__name__
uncamelized = re.sub(
r"[A-Z]",
lambda m: "_%s" % m.group(0).lower(),
referred_name,
)[1:]
pluralized = _pluralizer.plural(uncamelized)
return pluralized
from sqlalchemy.ext.automap import automap_base
Base = automap_base()
engine = create_engine("sqlite:///mydatabase.db")
Base.prepare(
autoload_with=engine,
classname_for_table=camelize_classname,
name_for_collection_relationship=pluralize_collection,
)Aus der obigen Zuordnung hätten wir nun die Klassen User und Address, wobei die Sammlung von User zu Address User.addresses heißt.
User, Address = Base.classes.User, Base.classes.Address
u1 = User(addresses=[Address(email="foo@bar.com")])Beziehungserkennung¶
Der Großteil dessen, was Automap leistet, ist die Generierung von relationship()-Strukturen basierend auf Fremdschlüsseln. Der Mechanismus, wie dies für Many-to-One- und One-to-Many-Beziehungen funktioniert, ist wie folgt:
Eine gegebene
Table, von der bekannt ist, dass sie einer bestimmten Klasse zugeordnet ist, wird aufForeignKeyConstraint-Objekte untersucht.Von jeder
ForeignKeyConstraintwird die entfernteTable-Objekt, falls vorhanden, mit der Klasse abgeglichen, der sie zugeordnet werden soll, andernfalls wird sie übersprungen.Da die untersuchte
ForeignKeyConstrainteiner Referenz von der unmittelbar zugeordneten Klasse entspricht, wird die Beziehung als Many-to-One eingerichtet, die auf die referenzierte Klasse verweist; ein entsprechender One-to-Many-Backref wird auf der referenzierten Klasse erstellt, die auf diese Klasse verweist.Wenn eine der Spalten, die Teil der
ForeignKeyConstraintist, nicht nullable ist (z. B.nullable=False), wird ein Schlüsselwortargumentrelationship.cascadevonall, delete-orphanzu den Schlüsselwortargumenten hinzugefügt, die an die Beziehung oder den Backref übergeben werden. Wenn dieForeignKeyConstraintangibt, dassForeignKeyConstraint.ondeletefür eine nicht-nullable oderSET NULLfür eine nullable Spaltensammlung aufCASCADEgesetzt ist, wird das Flagrelationship.passive_deletesin der Menge der Beziehungs-Schlüsselwortargumente aufTruegesetzt. Beachten Sie, dass nicht alle Backends die Reflexion von ON DELETE unterstützen.Die Namen der Beziehungen werden mithilfe der aufrufbaren Funktionen
AutomapBase.prepare.name_for_scalar_relationshipundAutomapBase.prepare.name_for_collection_relationshipermittelt. Es ist wichtig zu beachten, dass die Standard-Beziehungsbenennung den Namen vom tatsächlichen Klassennamen ableitet. Wenn Sie einer bestimmten Klasse einen expliziten Namen gegeben haben, indem Sie sie deklariert haben, oder ein alternatives Schema für Klassennamen angegeben haben, ist dies der Name, von dem der Beziehungsname abgeleitet wird.Die Klassen werden auf eine vorhandene zugeordnete Eigenschaft mit diesen Namen untersucht. Wenn eine auf einer Seite vorhanden ist, aber auf der anderen Seite keine, versucht
AutomapBase, auf der fehlenden Seite eine Beziehung zu erstellen, und verwendet dann den Parameterrelationship.back_populates, um die neue Beziehung auf die andere Seite zu verweisen.Im üblichen Fall, in dem auf keiner Seite eine Beziehung besteht, erstellt
AutomapBase.prepare()einerelationship()auf der "Many-to-One"-Seite und gleicht diese mit der anderen Seite über den Parameterrelationship.backrefab.Die Erstellung der
relationship()und optional derbackref()wird an die FunktionAutomapBase.prepare.generate_relationshipübergeben, die vom Endbenutzer bereitgestellt werden kann, um die anrelationship()oderbackref()übergebenen Argumente zu erweitern oder benutzerdefinierte Implementierungen dieser Funktionen zu nutzen.
Benutzerdefinierte Beziehungsargumente¶
Der Hook AutomapBase.prepare.generate_relationship kann verwendet werden, um Beziehungen Parameter hinzuzufügen. Für die meisten Fälle können wir die bestehende Funktion generate_relationship() verwenden, um das Objekt zurückzugeben, nachdem das gegebene Schlüsselwortwörterbuch mit unseren eigenen Argumenten erweitert wurde.
Unten ist eine Illustration, wie relationship.cascade und relationship.passive_deletes Optionen an alle One-to-Many-Beziehungen gesendet werden.
from sqlalchemy.ext.automap import generate_relationship
from sqlalchemy.orm import interfaces
def _gen_relationship(
base, direction, return_fn, attrname, local_cls, referred_cls, **kw
):
if direction is interfaces.ONETOMANY:
kw["cascade"] = "all, delete-orphan"
kw["passive_deletes"] = True
# make use of the built-in function to actually return
# the result.
return generate_relationship(
base, direction, return_fn, attrname, local_cls, referred_cls, **kw
)
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine
# automap base
Base = automap_base()
engine = create_engine("sqlite:///mydatabase.db")
Base.prepare(autoload_with=engine, generate_relationship=_gen_relationship)Many-to-Many-Beziehungen¶
automap generiert Many-to-Many-Beziehungen, z. B. solche, die ein secondary-Argument enthalten. Der Prozess zur Erzeugung dieser ist wie folgt:
Eine gegebene
Tablewird aufForeignKeyConstraint-Objekte untersucht, bevor ihr eine zugeordnete Klasse zugewiesen wurde.Wenn die Tabelle zwei und exakt zwei
ForeignKeyConstraint-Objekte enthält und alle Spalten innerhalb dieser Tabelle Mitglieder dieser beidenForeignKeyConstraint-Objekte sind, wird die Tabelle als "sekundäre" Tabelle angenommen und nicht direkt zugeordnet.Die beiden (oder eine, für selbst-referenzielle) externen Tabellen, auf die die
Tableverweist, werden mit den Klassen abgeglichen, denen sie zugeordnet werden sollen, falls vorhanden.Wenn zugeordnete Klassen für beide Seiten gefunden werden, wird ein bidirektionales Many-to-Many-
relationship()/backref()-Paar zwischen den beiden Klassen erstellt.Die Überschreibungslogik für Many-to-Many funktioniert genauso wie für One-to-Many/Many-to-One; die Funktion
generate_relationship()wird aufgerufen, um die Strukturen zu generieren, und bestehende Attribute werden beibehalten.
Beziehungen mit Vererbung¶
automap generiert keine Beziehungen zwischen zwei Klassen, die sich in einer Vererbungsbeziehung befinden. Das heißt, mit zwei Klassen, die wie folgt gegeben sind:
class Employee(Base):
__tablename__ = "employee"
id = Column(Integer, primary_key=True)
type = Column(String(50))
__mapper_args__ = {
"polymorphic_identity": "employee",
"polymorphic_on": type,
}
class Engineer(Employee):
__tablename__ = "engineer"
id = Column(Integer, ForeignKey("employee.id"), primary_key=True)
__mapper_args__ = {
"polymorphic_identity": "engineer",
}Der Fremdschlüssel von Engineer zu Employee wird nicht für eine Beziehung verwendet, sondern zur Etablierung einer Joined-Vererbung zwischen den beiden Klassen.
Beachten Sie, dass dies bedeutet, dass Automap keine Beziehungen für Fremdschlüssel generiert, die von einer Unterklasse zu einer Oberklasse verknüpfen. Wenn eine Zuordnung tatsächliche Beziehungen von Unterklasse zu Oberklasse enthält, müssen diese explizit sein. Unten, da wir zwei separate Fremdschlüssel von Engineer zu Employee haben, müssen wir sowohl die gewünschte Beziehung als auch die inherit_condition einrichten, da dies Dinge sind, die SQLAlchemy nicht erraten kann.
class Employee(Base):
__tablename__ = "employee"
id = Column(Integer, primary_key=True)
type = Column(String(50))
__mapper_args__ = {
"polymorphic_identity": "employee",
"polymorphic_on": type,
}
class Engineer(Employee):
__tablename__ = "engineer"
id = Column(Integer, ForeignKey("employee.id"), primary_key=True)
favorite_employee_id = Column(Integer, ForeignKey("employee.id"))
favorite_employee = relationship(
Employee, foreign_keys=favorite_employee_id
)
__mapper_args__ = {
"polymorphic_identity": "engineer",
"inherit_condition": id == Employee.id,
}Behandlung einfacher Namenskonflikte¶
Bei Namenskonflikten während der Zuordnung überschreiben Sie bei Bedarf classname_for_table(), name_for_scalar_relationship() und name_for_collection_relationship(). Zum Beispiel, wenn Automap versucht, eine Many-to-One-Beziehung genauso zu benennen wie eine vorhandene Spalte, kann bedingt eine alternative Konvention ausgewählt werden. Angenommen, ein Schema:
CREATE TABLE table_a (
id INTEGER PRIMARY KEY
);
CREATE TABLE table_b (
id INTEGER PRIMARY KEY,
table_a INTEGER,
FOREIGN KEY(table_a) REFERENCES table_a(id)
);Das obige Schema ordnet zunächst die table_a-Tabelle als Klasse namens table_a zu. Anschließend ordnet es eine Beziehung auf die Klasse für table_b mit demselben Namen wie diese zugeordnete Klasse, z. B. table_a, zu. Dieser Beziehungsname steht im Konflikt mit der Mapping-Spalte table_b.table_a und führt bei der Zuordnung zu einem Fehler.
Diesen Konflikt können wir wie folgt durch die Verwendung eines Unterstrichs lösen.
def name_for_scalar_relationship(
base, local_cls, referred_cls, constraint
):
name = referred_cls.__name__.lower()
local_table = local_cls.__table__
if name in local_table.columns:
newname = name + "_"
warnings.warn(
"Already detected name %s present. using %s" % (name, newname)
)
return newname
return name
Base.prepare(
autoload_with=engine,
name_for_scalar_relationship=name_for_scalar_relationship,
)Alternativ können wir den Namen auf der Spaltenseite ändern. Die zugeordneten Spalten können mit der unter Explicitly Naming Declarative Mapped Columns beschriebenen Technik modifiziert werden, indem die Spalte explizit einem neuen Namen zugewiesen wird.
Base = automap_base()
class TableB(Base):
__tablename__ = "table_b"
_table_a = Column("table_a", ForeignKey("table_a.id"))
Base.prepare(autoload_with=engine)Automap mit expliziten Deklarationen verwenden¶
Wie bereits erwähnt, ist Automap unabhängig von der Reflexion und kann jede Sammlung von Table-Objekten innerhalb einer MetaData-Sammlung nutzen. Daraus folgt, dass Automap auch verwendet werden kann, um fehlende Beziehungen zu generieren, wenn ein ansonsten vollständiges Modell die Tabellenmetadaten vollständig definiert.
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import Column, Integer, String, ForeignKey
Base = automap_base()
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
name = Column(String)
class Address(Base):
__tablename__ = "address"
id = Column(Integer, primary_key=True)
email = Column(String)
user_id = Column(ForeignKey("user.id"))
# produce relationships
Base.prepare()
# mapping is complete, with "address_collection" and
# "user" relationships
a1 = Address(email="u1")
a2 = Address(email="u2")
u1 = User(address_collection=[a1, a2])
assert a1.user is u1Oben, bei weitgehend vollständigen User und Address-Mappings, ermöglichte der auf Address.user_id definierte ForeignKey die Generierung eines bidirektionalen Beziehungspaares Address.user und User.address_collection auf den zugeordneten Klassen.
Beachten Sie, dass bei der Unterklassifizierung von AutomapBase die Methode AutomapBase.prepare() erforderlich ist; wenn sie nicht aufgerufen wird, befinden sich die von uns deklarierten Klassen in einem nicht zugeordneten Zustand.
Spaltendefinitionen abfangen¶
Die Objekte MetaData und Table unterstützen einen Event-Hook DDLEvents.column_reflect(), der verwendet werden kann, um die von einer Datenbankspalte reflektierten Informationen abzufangen, bevor das Column-Objekt konstruiert wird. Wenn wir beispielsweise Spalten nach einer Benennungskonvention wie "attr_<columnname>" zuordnen wollten, könnte das Ereignis wie folgt angewendet werden:
@event.listens_for(Base.metadata, "column_reflect")
def column_reflect(inspector, table, column_info):
# set column.key = "attr_<lower_case_name>"
column_info["key"] = "attr_%s" % column_info["name"].lower()
# run reflection
Base.prepare(autoload_with=engine)Neu in Version 1.4.0b2: Das Ereignis DDLEvents.column_reflect() kann auf ein MetaData-Objekt angewendet werden.
Siehe auch
Automating Column Naming Schemes from Reflected Tables – in der ORM-Mapping-Dokumentation
API-Referenz¶
| Objektname | Beschreibung |
|---|---|
automap_base([declarative_base], **kw) |
Erzeugt eine deklarative Automap-Basis. |
Basisklasse für ein „Automap“-Schema. |
|
classname_for_table(base, tablename, table) |
Gibt den Klassennamen zurück, der für einen Tabellennamen verwendet werden soll. |
generate_relationship(base, direction, return_fn, attrname, ..., **kw) |
Generiert ein |
name_for_collection_relationship(base, local_cls, referred_cls, constraint) |
Gibt den Attributnamen zurück, der verwendet werden soll, um von einer Klasse zu einer anderen für eine Sammlungsreferenz zu verweisen. |
name_for_scalar_relationship(base, local_cls, referred_cls, constraint) |
Gibt den Attributnamen zurück, der verwendet werden soll, um von einer Klasse zu einer anderen für eine Skalarobjekt-Referenz zu verweisen. |
- Funktion sqlalchemy.ext.automap.automap_base(declarative_base: Type[Any] | None = None, **kw: Any) → Any¶
Erzeugt eine deklarative Automap-Basis.
Diese Funktion erzeugt eine neue Basisklasse, die ein Produkt der Klasse
AutomapBasesowie einer deklarativen Basis ist, die vondeclarative_base()erzeugt wurde.Alle Parameter außer
declarative_basesind Schlüsselwortargumente, die direkt an die Funktiondeclarative_base()übergeben werden.- Parameter:
declarative_base¶ – eine vorhandene Klasse, die von
declarative_base()erzeugt wurde. Wenn dies übergeben wird, ruft die Funktiondeclarative_base()nicht mehr selbst auf und alle anderen Schlüsselwortargumente werden ignoriert.**kw¶ – Schlüsselwortargumente werden an
declarative_base()weitergegeben.
- Klasse sqlalchemy.ext.automap.AutomapBase¶
Basisklasse für ein „Automap“-Schema.
Die Klasse
AutomapBasekann mit der „deklarativen Basisklasse“ verglichen werden, die von der Funktiondeclarative_base()erzeugt wird. In der Praxis wird die KlasseAutomapBaseimmer als Mixin zusammen mit einer tatsächlichen deklarativen Basis verwendet.Eine neue, unterklassifizierbare
AutomapBasewird typischerweise über die Funktionautomap_base()instanziiert.Siehe auch
-
Attribut
sqlalchemy.ext.automap.AutomapBase.by_module: ClassVar[ByModuleProperties]¶ Eine Instanz von
Properties, die eine hierarchische Struktur von punktgetrennten Modulnamen, die mit Klassen verknüpft sind, enthält.Diese Sammlung ist eine Alternative zur Sammlung
AutomapBase.classesund nützlich, wenn der ParameterAutomapBase.prepare.modulename_for_tableverwendet wird, der verschiedenen__module__-Attributen für generierte Klassen zugewiesen wird.Das Standard-
__module__einer von Automap generierten Klasse istsqlalchemy.ext.automap; der Zugriff auf diesen Namensraum überAutomapBase.by_modulesieht wie folgt aus:User = Base.by_module.sqlalchemy.ext.automap.User
Wenn eine Klasse einen
__module__vonmymodule.accounthätte, sieht der Zugriff auf diesen Namensraum wie folgt aus:MyClass = Base.by_module.mymodule.account.MyClass
Neu in Version 2.0.
-
Attribut
sqlalchemy.ext.automap.AutomapBase.classes: ClassVar[Properties[Type[Any]]]¶ Eine Instanz von
Properties, die Klassen enthält.Dieses Objekt verhält sich weitgehend wie die Sammlung
.ceiner Tabelle. Klassen sind unter dem Namen vorhanden, unter dem sie gegeben wurden, z. B.Base = automap_base() Base.prepare(autoload_with=some_engine) User, Address = Base.classes.User, Base.classes.Address
Für Klassennamen, die mit einem Methodennamen von
Properties, wie z. B.items(), kollidieren, wird auch die Getitem-Form unterstützt.Item = Base.classes["items"]
-
Attribut
sqlalchemy.ext.automap.AutomapBase.metadata: ClassVar[MetaData]¶ Bezieht sich auf die
MetaData-Sammlung, die für neueTable-Objekte verwendet wird.Siehe auch
-
Klassenmethode
sqlalchemy.ext.automap.AutomapBase.prepare(autoload_with: Engine | None = None, engine: Any | None = None, reflect: bool = False, schema: str | None = None, classname_for_table: PythonNameForTableType | None = None, modulename_for_table: PythonNameForTableType | None = None, collection_class: Any | None = None, name_for_scalar_relationship: NameForScalarRelationshipType | None = None, name_for_collection_relationship: NameForCollectionRelationshipType | None = None, generate_relationship: GenerateRelationshipType | None = None, reflection_options: Dict[_KT, _VT] | immutabledict[_KT, _VT] = {}) → None¶ Extrahiert zugeordnete Klassen und Beziehungen aus den
MetaDataund führt Zuordnungen durch.Für eine vollständige Dokumentation und Beispiele siehe Grundlegende Verwendung.
- Parameter:
autoload_with¶ – eine
Engineoder einConnection, mit der/dem eine Schemareflexion durchgeführt werden soll; wenn angegeben, wird die MethodeMetaData.reflect()im Geltungsbereich dieser Methode aufgerufen.engine¶ –
Legacy; verwenden Sie
AutomapBase.autoload_with. Wird verwendet, um dieEngineoderConnectionanzugeben, mit der Tabellen reflektiert werden sollen, wennAutomapBase.reflectTrue ist.Veraltet seit Version 1.4: Der Parameter
AutomapBase.prepare.engineist veraltet und wird in einer zukünftigen Version entfernt. Bitte verwenden Sie den ParameterAutomapBase.prepare.autoload_with.reflect¶ –
Legacy; verwenden Sie
AutomapBase.autoload_with. Zeigt an, dassMetaData.reflect()aufgerufen werden soll.Veraltet seit Version 1.4: Der Parameter
AutomapBase.prepare.reflectist veraltet und wird in einer zukünftigen Version entfernt. Reflexion wird aktiviert, wennAutomapBase.prepare.autoload_withübergeben wird.classname_for_table¶ – aufrufbare Funktion, die verwendet wird, um neue Klassennamen zu erzeugen, gegeben einen Tabellennamen. Standardmäßig
classname_for_table().modulename_for_table¶ –
aufrufbare Funktion, die verwendet wird, um das effektive
__module__für eine intern generierte Klasse zu erzeugen, um mehrere Klassen mit demselben Namen in einer einzigen Automap-Basis zu ermöglichen, die sich in unterschiedlichen „Modulen“ befinden würden.Standardmäßig
None, was angibt, dass__module__nicht explizit gesetzt wird; die Python-Laufzeitumgebung verwendet den Wertsqlalchemy.ext.automapfür diese Klassen.Bei der Zuweisung von
__module__zu generierten Klassen können diese anhand punktgetrennter Modulnamen über die SammlungAutomapBase.by_moduleabgerufen werden. Klassen, denen ein explizites__module__über diesen Hook zugewiesen wurde, werden **nicht** in die SammlungAutomapBase.classes, sondern nur inAutomapBase.by_moduleaufgenommen.Neu in Version 2.0.
name_for_scalar_relationship¶ – aufrufbare Funktion, die verwendet wird, um Beziehungsnamen für Skalar-Beziehungen zu erzeugen. Standardmäßig
name_for_scalar_relationship().name_for_collection_relationship¶ – aufrufbare Funktion, die verwendet wird, um Beziehungsnamen für sammlungsorientierte Beziehungen zu erzeugen. Standardmäßig
name_for_collection_relationship().generate_relationship¶ – aufrufbare Funktion, die verwendet wird, um tatsächlich
relationship()undbackref()-Konstrukte zu generieren. Standardmäßiggenerate_relationship().collection_class¶ – die Python-Sammlungsklasse, die verwendet wird, wenn ein neues
relationship()-Objekt erstellt wird, das eine Sammlung darstellt. Standardmäßiglist.schema¶ –
Schemaname, der bei der Reflexion von Tabellen unter Verwendung des Parameters
AutomapBase.prepare.autoload_withreflektiert werden soll. Der Name wird an den ParameterMetaData.reflect.schemavonMetaData.reflect()übergeben. Wenn dieser weggelassen wird, wird das Standard-Schema der Datenbankverbindung verwendet.Hinweis
Der Parameter
AutomapBase.prepare.schemaunterstützt die Reflexion eines einzelnen Schemas gleichzeitig. Um Tabellen aus vielen Schemas einzubeziehen, verwenden Sie mehrere Aufrufe vonAutomapBase.prepare().Eine Übersicht über die Generierung von Mappings aus mehreren Schemas, einschließlich der Verwendung zusätzlicher Benennungskonventionen zur Lösung von Tabellennamenkonflikten, finden Sie im Abschnitt Generierung von Mappings aus mehreren Schemas.
Neu in Version 2.0:
AutomapBase.prepare()kann beliebig oft direkt aufgerufen werden, wobei die bereits verarbeiteten Tabellen verfolgt werden, um eine erneute Verarbeitung zu vermeiden.reflection_options¶ –
Wenn vorhanden, wird dieses Dictionary von Optionen an
MetaData.reflect()übergeben, um allgemeine reflektionsspezifische Optionen wieonlyund/oder dialektspezifische Optionen wieoracle_resolve_synonymsbereitzustellen.Neu in Version 1.4.
-
Attribut
- Funktion sqlalchemy.ext.automap.classname_for_table(base: Type[Any], tablename: str, table: Table) → str¶
Gibt den Klassennamen zurück, der für einen Tabellennamen verwendet werden soll.
Die Standardimplementierung ist:
return str(tablename)
Alternative Implementierungen können über den Parameter
AutomapBase.prepare.classname_for_tableangegeben werden.- Parameter:
- Gibt zurück:
eine Zeichenkettenklasse.
Hinweis
In Python 2 muss der für den Klassennamen verwendete String ein Nicht-Unicode-Objekt sein, z. B. ein
str()-Objekt. Das Attribut.namevonTableist typischerweise eine Python-Unicode-Unterklasse, daher sollte die Funktionstr()nach Berücksichtigung von Nicht-ASCII-Zeichen auf diesen Namen angewendet werden.
- function sqlalchemy.ext.automap.name_for_scalar_relationship(base: Type[Any], local_cls: Type[Any], referred_cls: Type[Any], constraint: ForeignKeyConstraint) → str¶
Gibt den Attributnamen zurück, der verwendet werden soll, um von einer Klasse zu einer anderen für eine Skalarobjekt-Referenz zu verweisen.
Die Standardimplementierung ist:
return referred_cls.__name__.lower()
Alternative Implementierungen können über den Parameter
AutomapBase.prepare.name_for_scalar_relationshipangegeben werden.- Parameter:
base¶ – die
AutomapBase-Klasse, die die Vorbereitung durchführt.local_cls¶ – die Klasse, die auf der lokalen Seite abgebildet werden soll.
referred_cls¶ – die Klasse, die auf der verweisenden Seite abgebildet werden soll.
constraint¶ – die
ForeignKeyConstraint, die zur Erzeugung dieser Beziehung inspiziert wird.
- function sqlalchemy.ext.automap.name_for_collection_relationship(base: Type[Any], local_cls: Type[Any], referred_cls: Type[Any], constraint: ForeignKeyConstraint) → str¶
Gibt den Attributnamen zurück, der verwendet werden soll, um von einer Klasse zu einer anderen für eine Sammlungsreferenz zu verweisen.
Die Standardimplementierung ist:
return referred_cls.__name__.lower() + "_collection"
Alternative Implementierungen können über den Parameter
AutomapBase.prepare.name_for_collection_relationshipangegeben werden.- Parameter:
base¶ – die
AutomapBase-Klasse, die die Vorbereitung durchführt.local_cls¶ – die Klasse, die auf der lokalen Seite abgebildet werden soll.
referred_cls¶ – die Klasse, die auf der verweisenden Seite abgebildet werden soll.
constraint¶ – die
ForeignKeyConstraint, die zur Erzeugung dieser Beziehung inspiziert wird.
- function sqlalchemy.ext.automap.generate_relationship(base: Type[Any], direction: RelationshipDirection, return_fn: Callable[..., Relationship[Any]] | Callable[..., ORMBackrefArgument], attrname: str, local_cls: Type[Any], referred_cls: Type[Any], **kw: Any) → Relationship[Any] | ORMBackrefArgument¶
Generiert ein
relationship()oderbackref()im Auftrag von zwei zugeordneten Klassen.Eine alternative Implementierung dieser Funktion kann über den Parameter
AutomapBase.prepare.generate_relationshipangegeben werden.Die Standardimplementierung dieser Funktion lautet wie folgt:
if return_fn is backref: return return_fn(attrname, **kw) elif return_fn is relationship: return return_fn(referred_cls, **kw) else: raise TypeError("Unknown relationship function: %s" % return_fn)
- Parameter:
base¶ – die
AutomapBase-Klasse, die die Vorbereitung durchführt.direction¶ – gibt die „Richtung“ der Beziehung an; dies ist eine von
ONETOMANY,MANYTOONE,MANYTOMANY.return_fn¶ – die Funktion, die standardmäßig zum Erstellen der Beziehung verwendet wird. Dies ist entweder
relationship()oderbackref(). Das Ergebnis der Funktionbackref()wird in einem zweiten Schritt verwendet, um eine neuerelationship()zu erzeugen, daher ist es entscheidend, dass benutzerdefinierte Implementierungen korrekt zwischen den beiden Funktionen unterscheiden, wenn eine benutzerdefinierte Beziehungsfunktion verwendet wird.attrname¶ – der Attributname, dem diese Beziehung zugewiesen wird. Wenn der Wert von
generate_relationship.return_fndie Funktionbackref()ist, dann ist dieser Name der Name, der dem Backref zugewiesen wird.local_cls¶ – die „lokale“ Klasse, zu der diese Beziehung oder dieser Backref lokal gehören wird.
referred_cls¶ – die „referenzierte“ Klasse, auf die sich die Beziehung oder der Backref bezieht.
**kw¶ – alle zusätzlichen Schlüsselwortargumente werden an die Funktion weitergegeben.
- Gibt zurück:
ein
relationship()- oderbackref()-Konstrukt, wie durch den Parametergenerate_relationship.return_fnvorgegeben.
Die Designs von flambé! dem Drachen und Der Alchemist wurden von Rotem Yaari erstellt und großzügig gespendet.
Erstellt mit Sphinx 7.2.6. Dokumentation zuletzt generiert: Di 11 Mär 2025 14:40:17 EDT