Storage layer#
Die Storage-Schicht in RESTAlchemy ist für das Persistieren von DM-Modellen und deren Wiederherstellung zuständig.
Sie bildet eine eigene Schicht zwischen Data Model (DM) und API.
Modulüberblick#
Wichtige Module für SQL-Storage:
restalchemy.storage.base- Abstrakte Interfaces für speicherbare Modelle und Collections.
restalchemy.storage.exceptions- Storage-spezifische Exceptions.
restalchemy.storage.sql.engines- Engine-Factory und Implementierungen für MySQL/PostgreSQL.
restalchemy.storage.sql.sessions- Datenbank-Sessions, Transaktionen, Session-Query-Cache.
restalchemy.storage.sql.orm- ORM-ähnliche Mixins und Collections (
SQLStorableMixin,ObjectCollection). restalchemy.storage.sql.tables- Tabellenabstraktion für ORM und Dialekte.
restalchemy.storage.sql.dialect.*- Dialekt-spezifische Query-Builder für MySQL und PostgreSQL.
Im Normalfall arbeiten Sie nur mit:
- DM-Modellen +
orm.SQLStorableMixin; engines.engine_factory.configure_factory()zur Konfiguration des Engines;Model.objectsund den Methodensave()/delete().
Architekturüberblick#
1. DM-Modell#
Sie definieren ein Modell, das von:
models.ModelWithUUID(oder einer anderenModel*-Basisklasse) undorm.SQLStorableMixin
erbt.
Beispiel (vereinfacht aus examples/dm_mysql_storage.py):
from restalchemy.dm import models, properties, relationships, types
from restalchemy.storage.sql import orm
class FooModel(models.ModelWithUUID, orm.SQLStorableMixin):
__tablename__ = "foos"
foo_field1 = properties.property(types.Integer(), required=True)
foo_field2 = properties.property(types.String(), default="foo_str")
class BarModel(models.ModelWithUUID, orm.SQLStorableMixin):
__tablename__ = "bars"
bar_field1 = properties.property(types.String(min_length=1, max_length=10))
foo = relationships.relationship(FooModel)
2. Engine und Sessions#
restalchemy.storage.sql.engines enthält eine engine_factory, die SQL-Engines verwaltet.
Typische Konfiguration:
from restalchemy.storage.sql import engines
engines.engine_factory.configure_factory(
db_url="mysql://user:password@127.0.0.1:3306/mydb",
)
Kernideen:
- Engine parst
db_url, konfiguriert Connection-Pool und Dialekt. - Session (
PgSQLSession/MySQLSession) führt Statements aus. session_manager(engine, session=None)(insessions.py) kapselt Workflows in Transaktionen.
3. ORM-Mixins und Collections#
restalchemy.storage.sql.orm stellt bereit:
SQLStorableMixin— Mixin für DM-Modelle, die in SQL gespeichert werden.ObjectCollection— Collection-API, erreichbar überModel.objects.
Verantwortlichkeiten:
SQLStorableMixin:- Verknüpft DM-Modell und Tabelle über
__tablename__undget_table(). - Implementiert
insert(),save(),update(),delete(). -
Konvertiert DM-Properties in speicherbare Werte und zurück.
-
ObjectCollection: - Methoden
get_all(),get_one(),get_one_or_none(),query(),count(). - Nutzt
restalchemy.dm.filterszur Beschreibung von WHERE-Bedingungen.
4. Dialekte und Tabellen#
Dialekt-Module (restalchemy.storage.sql.dialect.*) und tables.SQLTable:
- Erzeugen SQL-Statements (SELECT/INSERT/UPDATE/DELETE).
- Binden Parameter.
- Führen Queries über Sessions aus.
Diese Komponenten sind intern; Sie müssen sie selten direkt verwenden.
5. Was das Lesen einer Zeile tut#
- Ein Modell ohne vorgeladene Beziehungen wird aus einer Tabelle gelesen, und seine Spalten werden unter ihren eigenen Namen selektiert. Ein Prefetch fügt einen JOIN hinzu; dann erhält jede Spalte einen Alias, damit zwei Tabellen gleichnamige Spalten selektieren können.
- Ein gespeichertes
NULList ein Wert, den niemand angegeben hat: der Default der Property greift, genau wie bei einem im Konstruktor ausgelassenen Wert. - Ein Wert, den der Typ selbst aus der gespeicherten Form baut —
UUID,Boolean, der vonUTCDateTimeZauf UTC gebrachte Zeitstempel — wird gegen diesen Typ nicht erneut geprüft. Alle anderen Typen werden wie bisher geprüft, und ebenso alles, was einen dieser drei erbt: eine Unterklasse behält die Umwandlung, kann aber eine eigene Regel haben. - Jedes Lesen kommt bei
restore_rowan — ein Modell wie eine ganze Seite —, also gehört dorthin, was ein Modell bei jedem Lesen tun will.restore_from_storageist ein Weg hinein und kein Weg, das Lesen zu ändern: Es zu überschreiben lässt eine Seite von Zeilen unberührt.
Lebenszyklus eines SQL-gestützten Modells#
- Modell definieren
- Von
ModelWithUUIDundSQLStorableMixinerben. __tablename__festlegen.-
Felder und Beziehungen über DM-Properties definieren.
-
Engine konfigurieren
-
Einmalig beim Start:
engine_factory.configure_factory(db_url=...). -
Tabellen/Migrationen
-
Mit
ra-new-migrationundra-apply-migrationDatenbank-Schema anlegen/ändern. -
CRUD-Operationen
- Instanzen erzeugen und
.save()aufrufen. - Über
Model.objects.get_all()/.get_one(filters=...)lesen. -
.delete()zum Löschen verwenden. -
Filter und komplexe Queries
-
Filter mit
restalchemy.dm.filtersaufbauen und anobjects.get_all()/get_one()übergeben. -
Transaktionen und Sessions (optional)
- Für feingranulare Kontrolle
session_manager()explizit verwenden.
Alle Schritte werden ausführlich im DM+SQL How-to und in examples/dm_mysql_storage.py sowie examples/dm_pg_storage.py gezeigt.