Zeilen erstellen - Die Session verwenden - INSERT¶
Nachdem wir nun eine Datenbank und eine Tabelle haben, können wir mit dem Hinzufügen von Daten beginnen.
Hier ist eine Erinnerung, wie die Tabelle aussehen würde, das sind die Daten, die wir hinzufügen möchten
| id | name | secret_name | age |
|---|---|---|---|
| 1 | Deadpond | Dive Wilson | null |
| 2 | Spider-Boy | Pedro Parqueador | null |
| 3 | Rusty-Man | Tommy Sharp | 48 |
Tabelle und Datenbank erstellen¶
Wir machen dort weiter, wo wir im letzten Kapitel aufgehört haben.
Das ist der Code, den wir hatten, um die Datenbank und die Tabelle zu erstellen, nichts Neues hier
from sqlmodel import Field, SQLModel, create_engine # (2)!
class Hero(SQLModel, table=True): # (3)!
id: int | None = Field(default=None, primary_key=True) # (4)!
name: str # (5)!
secret_name: str # (6)!
age: int | None = None # (7)!
sqlite_file_name = "database.db" # (8)!
sqlite_url = f"sqlite:///{sqlite_file_name}" # (9)!
engine = create_engine(sqlite_url, echo=True) # (10)!
def create_db_and_tables(): # (11)!
SQLModel.metadata.create_all(engine) # (12)!
# More code here later 👈
if __name__ == "__main__": # (13)!
create_db_and_tables() # (14)!
- Importieren Sie
Optionalaustyping, um Felder zu deklarieren, dieNonesein könnten. - Importieren Sie die Dinge, die wir aus
sqlmodelbenötigen:Field,SQLModel,create_engine. -
Erstellen Sie die Modellklasse
Hero, die die Tabelleheroin der Datenbank darstellt.Und markieren Sie diese Klasse auch als Tabellenmodell mit
table=True. -
Erstellen Sie das Feld
idEs könnte
Nonesein, bis die Datenbank ihm einen Wert zuweist, daher annotieren wir es mitOptional.Es ist ein Primärschlüssel, daher verwenden wir
Field()und das Argumentprimary_key=True. -
Erstellen Sie das Feld
name.Es ist erforderlich, daher gibt es keinen Standardwert und es ist nicht
Optional. -
Erstellen Sie das Feld
secret_name.Ebenfalls erforderlich.
-
Erstellen Sie das Feld
age.Es ist nicht erforderlich, der Standardwert ist
None.In der Datenbank wird der Standardwert
NULLsein, das SQL-Äquivalent vonNone.Da dieses Feld
None(und in der DatenbankNULL) sein könnte, annotieren wir es mitOptional. -
Schreiben Sie den Namen der Datenbankdatei.
- Verwenden Sie den Namen der Datenbankdatei, um die Datenbank-URL zu erstellen.
-
Erstellen Sie die Engine mit der URL.
Dies erstellt die Datenbank noch nicht, es wird zu diesem Zeitpunkt noch keine Datei oder Tabelle erstellt, nur das Engine-Objekt, das die Verbindungen mit dieser spezifischen Datenbank verwaltet und spezifische Unterstützung für SQLite bietet (basierend auf der URL).
-
Legen Sie den Code, der Nebeneffekte erzeugt, in eine Funktion.
In diesem Fall nur eine Zeile, die die Datenbankdatei mit der Tabelle erstellt.
-
Erstellen Sie alle Tabellen, die automatisch in
SQLModel.metadataregistriert wurden. -
Fügen Sie einen Hauptblock oder eine "Top-Level-Skriptumgebung" hinzu.
Und fügen Sie eine Logik hinzu, die ausgeführt werden soll, wenn dies direkt mit Python aufgerufen wird, wie z.B.
$ python app.py // Execute all the stuff and show the output...aber das wird nicht ausgeführt, wenn etwas aus diesem Modul importiert wird, wie z.B.
from app import Hero -
Rufen Sie in diesem Hauptblock die Funktion auf, die die Datenbankdatei und die Tabelle erstellt.
So wird beim Aufruf mit
$ python app.py // Doing stuff ✨...wird die Datenbankdatei und die Tabelle erstellt.
from typing import Optional # (1)!
from sqlmodel import Field, SQLModel, create_engine # (2)!
class Hero(SQLModel, table=True): # (3)!
id: Optional[int] = Field(default=None, primary_key=True) # (4)!
name: str # (5)!
secret_name: str # (6)!
age: Optional[int] = None # (7)!
sqlite_file_name = "database.db" # (8)!
sqlite_url = f"sqlite:///{sqlite_file_name}" # (9)!
engine = create_engine(sqlite_url, echo=True) # (10)!
def create_db_and_tables(): # (11)!
SQLModel.metadata.create_all(engine) # (12)!
# More code here later 👈
if __name__ == "__main__": # (13)!
create_db_and_tables() # (14)!
- Importieren Sie
Optionalaustyping, um Felder zu deklarieren, dieNonesein könnten. - Importieren Sie die Dinge, die wir aus
sqlmodelbenötigen:Field,SQLModel,create_engine. -
Erstellen Sie die Modellklasse
Hero, die die Tabelleheroin der Datenbank darstellt.Und markieren Sie diese Klasse auch als Tabellenmodell mit
table=True. -
Erstellen Sie das Feld
idEs könnte
Nonesein, bis die Datenbank ihm einen Wert zuweist, daher annotieren wir es mitOptional.Es ist ein Primärschlüssel, daher verwenden wir
Field()und das Argumentprimary_key=True. -
Erstellen Sie das Feld
name.Es ist erforderlich, daher gibt es keinen Standardwert und es ist nicht
Optional. -
Erstellen Sie das Feld
secret_name.Ebenfalls erforderlich.
-
Erstellen Sie das Feld
age.Es ist nicht erforderlich, der Standardwert ist
None.In der Datenbank wird der Standardwert
NULLsein, das SQL-Äquivalent vonNone.Da dieses Feld
None(und in der DatenbankNULL) sein könnte, annotieren wir es mitOptional. -
Schreiben Sie den Namen der Datenbankdatei.
- Verwenden Sie den Namen der Datenbankdatei, um die Datenbank-URL zu erstellen.
-
Erstellen Sie die Engine mit der URL.
Dies erstellt die Datenbank noch nicht, es wird zu diesem Zeitpunkt noch keine Datei oder Tabelle erstellt, nur das Engine-Objekt, das die Verbindungen mit dieser spezifischen Datenbank verwaltet und spezifische Unterstützung für SQLite bietet (basierend auf der URL).
-
Legen Sie den Code, der Nebeneffekte erzeugt, in eine Funktion.
In diesem Fall nur eine Zeile, die die Datenbankdatei mit der Tabelle erstellt.
-
Erstellen Sie alle Tabellen, die automatisch in
SQLModel.metadataregistriert wurden. -
Fügen Sie einen Hauptblock oder eine "Top-Level-Skriptumgebung" hinzu.
Und fügen Sie eine Logik hinzu, die ausgeführt werden soll, wenn dies direkt mit Python aufgerufen wird, wie z.B.
$ python app.py // Execute all the stuff and show the output...aber das wird nicht ausgeführt, wenn etwas aus diesem Modul importiert wird, wie z.B.
from app import Hero -
Rufen Sie in diesem Hauptblock die Funktion auf, die die Datenbankdatei und die Tabelle erstellt.
So wird beim Aufruf mit
$ python app.py // Doing stuff ✨...wird die Datenbankdatei und die Tabelle erstellt.
Nachdem wir nun die Datenbank und die Tabelle erstellen können, werden wir von diesem Punkt aus fortfahren und weiteren Code in derselben Datei hinzufügen, um die Daten zu erstellen.
Daten mit SQL erstellen¶
Bevor wir mit Python-Code arbeiten, sehen wir uns an, wie wir Daten mit SQL erstellen können.
Nehmen wir an, wir möchten den Datensatz/die Zeile für Deadpond in unsere Datenbank einfügen.
Das können wir mit folgendem SQL-Code tun
INSERT INTO "hero" ("name", "secret_name")
VALUES ("Deadpond", "Dive Wilson");
Das bedeutet, mehr oder weniger
Hallo SQL-Datenbank 👋, bitte
INSERTetwas (erstelle einen Datensatz/eine Zeile)INTOdie Tabelle"hero".Ich möchte, dass Sie eine Zeile mit einigen Werten in diesen spezifischen Spalten einfügen
"name""secret_name"Und die Werte, die ich möchte, dass Sie in diese Spalten einfügen, sind
"Deadpond""Dive Wilson"
Versuchen Sie es im DB Explorer für SQLite¶
Sie können diese SQL-Anweisung im DB Explorer für SQLite ausprobieren.
Stellen Sie sicher, dass Sie dieselbe Datenbank öffnen, die wir bereits erstellt haben, indem Sie auf Open Database klicken und dieselbe database.db-Datei auswählen.
Tipp
Wenn Sie diese database.db-Datei mit der Tabelle hero nicht haben, können Sie sie neu erstellen, indem Sie das Python-Programm von oben ausführen. 👆
Gehen Sie dann zum Reiter Execute SQL und kopieren Sie das obige SQL.
Es würde so aussehen

Klicken Sie auf die Schaltfläche "Alle ausführen" ▶.
Dann können Sie zum Reiter Browse Data gehen und Sie werden Ihren neu erstellten Datensatz/Ihre Zeile sehen

Daten in einer Datenbank und Daten im Code¶
Wenn wir mit einer Datenbank (SQL oder einer anderen Art) in einer Programmiersprache arbeiten, werden wir immer einige Daten im Speicher haben, in Objekten und Variablen, die wir in unserem Code erstellen, und es werden einige Daten in der Datenbank sein.
Wir holen ständig einige der Daten aus der Datenbank und legen sie in den Speicher, in Variablen.
Ebenso erstellen wir ständig Variablen und Objekte mit Daten in unserem Code, die wir dann in der Datenbank speichern wollen, also senden wir sie irgendwie.
In einigen Fällen können wir sogar einige Daten im Speicher erstellen und sie dann ändern und aktualisieren, bevor wir sie in der Datenbank speichern.
Vielleicht entscheiden wir sogar mit einer Logik im Code, dass wir die Daten nicht mehr in der Datenbank speichern wollen, und entfernen sie dann einfach. 🔥 Und wir haben diese Daten nur im Speicher behandelt, ohne sie hin und her zur Datenbank zu senden.
SQLModel tut alles, was es kann (eigentlich über SQLAlchemy), um diese Interaktion so einfach, intuitiv und vertraut oder "programmierungsnah" wie möglich zu gestalten. ✨
Aber diese Aufteilung der beiden Orte, an denen sich Daten zu jedem Zeitpunkt befinden können (im Speicher oder in der Datenbank), ist immer vorhanden. Und es ist wichtig, dass Sie sie im Hinterkopf behalten. 🤓
Daten mit Python und SQLModel erstellen¶
Jetzt erstellen wir dieselbe Zeile in Python.
Löschen Sie zuerst die Datei database.db, damit wir von vorne beginnen können.
Da wir Python-Code mit Daten im Speicher ausführen und die Datenbank ein unabhängiges System ist (eine externe SQLite-Datei oder ein externer Datenbankserver), müssen wir zwei Schritte durchführen
- die Daten in Python, im Speicher erstellen (in einer Variablen)
- die Daten in der Datenbank speichern/senden
Modellinstanz erstellen¶
Beginnen wir mit dem ersten Schritt: die Daten im Speicher erstellen.
Wir haben bereits eine Klasse Hero erstellt, die die Tabelle hero in der Datenbank darstellt.
Jede Instanz, die wir erstellen, repräsentiert die Daten einer Zeile in der Datenbank.
Der erste Schritt ist also, einfach eine Instanz von Hero zu erstellen.
Wir erstellen gleich 3, für die 3 Helden
# Code above omitted 👆
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Tipp
Der obige Code in dieser Datei (der weggelassene Code) ist derselbe Code, den Sie oben in diesem Kapitel sehen.
Derselbe Code, den wir zuvor verwendet haben, um das Hero-Modell zu erstellen.
Wir legen das in eine Funktion create_heroes(), um sie später aufzurufen, sobald wir sie fertiggestellt haben.
Wenn Sie den Code interaktiv ausprobieren, könnten Sie das auch direkt schreiben.
Eine Session erstellen¶
Bisher haben wir nur die Engine verwendet, um mit der Datenbank zu interagieren.
Die Engine ist dieses einzelne Objekt, das wir mit dem gesamten Code teilen und das für die Kommunikation mit der Datenbank zuständig ist, die Verbindungen verwaltet (bei Verwendung einer Serverdatenbank wie PostgreSQL oder MySQL) usw.
Aber bei der Arbeit mit SQLModel werden Sie hauptsächlich ein weiteres Werkzeug verwenden, das darüber sitzt, die Session.
Im Gegensatz zur Engine, die für die gesamte Anwendung einmalig ist, erstellen wir für jede Gruppe von Operationen mit der Datenbank, die zusammengehören, eine neue Session.
Tatsächlich benötigt und verwendet die Session eine Engine.
Wenn wir zum Beispiel eine Webanwendung haben, würden wir normalerweise für jede Anfrage eine einzige Session haben.
Wir würden dieselbe Engine in allem Code wiederverwenden, überall in der Anwendung (von allen Anfragen gemeinsam genutzt). Aber für jede Anfrage würden wir eine neue Session erstellen und verwenden. Und sobald die Anfrage beendet ist, würden wir die Session schließen.
Der erste Schritt ist der Import der Klasse Session
from sqlmodel import Field, Session, SQLModel, create_engine
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Dann können wir eine neue Session erstellen
# Code above omitted 👆
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Die neue Session nimmt eine engine als Parameter. Und sie wird die Engine im Hintergrund verwenden.
Tipp
Eine bessere Möglichkeit, eine Session mit einem with-Block zu erstellen, sehen wir später.
Modellinstanzen zur Session hinzufügen¶
Nachdem wir nun einige Heldenmodellinstanzen (einige Objekte im Speicher) und eine Session haben, besteht der nächste Schritt darin, sie zur Session hinzuzufügen
# Code above omitted 👆
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Zu diesem Zeitpunkt sind unsere Helden noch nicht in der Datenbank gespeichert.
Und das ist einer der Fälle, in denen eine Session, die unabhängig von einer Engine ist, Sinn ergibt.
Die Session speichert im Speicher alle Objekte, die später in der Datenbank gespeichert werden sollen.
Und wenn wir bereit sind, können wir diese Änderungen committen, und dann wird die Session die Engine im Hintergrund verwenden, um alle Daten zu speichern, indem sie die entsprechende SQL-Anweisung an die Datenbank sendet, und auf diese Weise werden alle Zeilen erstellt. Alles in einem einzigen Batch.
Dies macht die Interaktionen mit der Datenbank effizienter (plus einige zusätzliche Vorteile).
Technische Details
Die Session erstellt eine neue Transaktion und führt den gesamten SQL-Code in dieser Transaktion aus.
Dies stellt sicher, dass die Daten in einem einzigen Batch gespeichert werden und dass entweder alles erfolgreich ist oder alles fehlschlägt, aber die Datenbank nicht in einem fehlerhaften Zustand hinterlässt.
Session-Änderungen committen¶
Nachdem wir die Helden nun in der Session haben und bereit sind, alles in der Datenbank zu speichern, können wir die Änderungen committen
# Code above omitted 👆
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Sobald diese Zeile ausgeführt wird, verwendet die Session die Engine, um alle Daten in der Datenbank zu speichern, indem sie die entsprechenden SQL-Anweisungen sendet.
Helden als Skript erstellen¶
Die Funktion zum Erstellen der Helden ist nun fertig.
Nun müssen wir nur noch sicherstellen, dass sie aufgerufen wird, wenn wir dieses Programm direkt mit Python ausführen.
Wir hatten bereits einen Hauptblock wie
if __name__ == "__main__":
create_db_and_tables()
Wir könnten die neue Funktion dort hinzufügen, wie
if __name__ == "__main__":
create_db_and_tables()
create_heroes()
Um die Dinge etwas besser zu organisieren, erstellen wir stattdessen eine neue Funktion main(), die den gesamten Code enthält, der ausgeführt werden soll, wenn er als eigenständiges Skript aufgerufen wird, und wir können dort die vorherige Funktion create_db_and_tables() und die neue Funktion create_heroes() hinzufügen.
# Code above omitted 👆
def main():
create_db_and_tables()
create_heroes()
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Und dann können wir diese einzelne main()-Funktion aus diesem Hauptblock aufrufen
# Code above omitted 👆
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Indem wir alles, was geschehen soll, wenn es als Skript aufgerufen wird, in einer einzigen Funktion zusammenfassen, können wir später leicht weiteren Code hinzufügen.
Und einige andere Codes könnten auch diese gleiche main()-Funktion importieren und verwenden, wenn es notwendig wäre.
Das Skript ausführen¶
Jetzt können wir unser Programm als Skript von der Konsole aus ausführen.
Da wir die Engine mit echo=True erstellt haben, wird sie den gesamten SQL-Code ausgeben, den sie ausführt
$ python app.py
// Some boilerplate, checking that the hero table already exists
INFO Engine BEGIN (implicit)
INFO Engine PRAGMA main.table_info("hero")
INFO Engine [raw sql] ()
INFO Engine COMMIT
// BEGIN a transaction automatically ✨
INFO Engine BEGIN (implicit)
// Our INSERT statement, it uses VALUES (?, ?, ?) as parameters
INFO Engine INSERT INTO hero (name, secret_name, age) VALUES (?, ?, ?)
// ...and these are the parameter values 🚀
INFO Engine [generated in 0.00013s] ('Deadpond', 'Dive Wilson', None)
// Again, for Spider-Boy
INFO Engine INSERT INTO hero (name, secret_name, age) VALUES (?, ?, ?)
INFO Engine [cached since 0.000755s ago] ('Spider-Boy', 'Pedro Parqueador', None)
// And now for Rusty-Man
INFO Engine INSERT INTO hero (name, secret_name, age) VALUES (?, ?, ?)
INFO Engine [cached since 0.001014s ago] ('Rusty-Man', 'Tommy Sharp', 48)
// All good? Yes, commit this transaction! 🎉
INFO Engine COMMIT
Wenn Sie jemals Git verwendet haben, funktioniert dies sehr ähnlich.
Wir verwenden session.add(), um neue Objekte (Modellinstanzen) zur Session hinzuzufügen (ähnlich wie git add).
Und das endet in einer Gruppe von Daten, die bereit zum Speichern sind, aber noch nicht gespeichert sind.
Wir können weitere Änderungen vornehmen, weitere Objekte hinzufügen usw.
Und wenn wir bereit sind, können wir alle Änderungen in einem einzigen Schritt committen (ähnlich wie git commit).
Die Session schließen¶
Die Session hält einige Ressourcen, wie z. B. Verbindungen von der Engine.
Sobald wir mit der Session fertig sind, sollten wir sie schließen, damit sie diese Ressourcen freigibt und ihre Bereinigung abschließt
# Code above omitted 👆
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
session = Session(engine)
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
session.close()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Aber was passiert, wenn wir vergessen, die Session zu schließen?
Oder wenn es eine Ausnahme im Code gibt und session.close() nie erreicht wird?
Dafür gibt es eine bessere Möglichkeit, die Session zu erstellen und zu schließen, nämlich mit einem with-Block. 👇
Eine Session in einem with-Block¶
Es ist gut zu wissen, wie die Session funktioniert und wie man sie manuell erstellt und schließt. Das kann nützlich sein, wenn Sie zum Beispiel den Code in einer interaktiven Session erkunden möchten (z. B. mit Jupyter).
Aber es gibt einen besseren Weg, die Session zu verwalten, nämlich mit einem with-Block
# Code above omitted 👆
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
# Code below omitted 👇
👀 Vollständige Dateivorschau
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
🤓 Andere Versionen und Varianten
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes():
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson")
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session:
session.add(hero_1)
session.add(hero_2)
session.add(hero_3)
session.commit()
def main():
create_db_and_tables()
create_heroes()
if __name__ == "__main__":
main()
Dies entspricht dem manuellen Erstellen der Session und dem anschließenden manuellen Schließen. Aber hier wird sie mit einem with-Block automatisch erstellt, wenn der with-Block beginnt und der Variablen session zugewiesen wird, und sie wird automatisch geschlossen, nachdem der with-Block beendet ist.
Und es funktioniert auch dann, wenn es eine Ausnahme im Code gibt. 😎
Den gesamten Code überprüfen¶
Werfen wir einen letzten Blick auf diese gesamte Datei. 🔍
Sie kennen bereits den gesamten ersten Teil für die Erstellung der Modellklasse Hero, die Engine und die Erstellung der Datenbank und Tabelle.
Konzentrieren wir uns auf den neuen Code
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
secret_name: str
age: int | None = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes(): # (1)!
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") # (2)!
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session: # (3)!
session.add(hero_1) # (4)!
session.add(hero_2)
session.add(hero_3)
session.commit() # (5)!
# (6)!
def main(): # (7)!
create_db_and_tables() # (8)!
create_heroes() # (9)!
if __name__ == "__main__": # (10)!
main() # (11)!
-
Wir verwenden eine Funktion
create_heroes(), um diese Logik zusammenzufassen. -
Erstellen Sie jedes der Objekte/Instanzen des
Hero-Modells.Jedes von ihnen repräsentiert die Daten für eine Zeile.
-
Verwenden Sie einen
with-Block, um eineSessionmit derenginezu erstellen.Die neue Session wird der Variablen
sessionzugewiesen.Und sie wird automatisch geschlossen, wenn der
with-Block beendet ist. -
Fügen Sie jedes der Objekte/Instanzen zur Session hinzu.
Jedes dieser Objekte repräsentiert eine Zeile in der Datenbank.
Sie warten dort alle in der Session darauf, gespeichert zu werden.
-
Commiten Sie die Änderungen an die Datenbank.
Dies sendet tatsächlich die Daten an die Datenbank.
Es wird automatisch eine Transaktion gestartet und alle Daten in einem einzigen Batch gespeichert.
-
Zu diesem Zeitpunkt, nachdem der
with-Block beendet ist, ist die Session automatisch geschlossen. -
Wir haben eine
main()-Funktion mit dem gesamten Code, der ausgeführt werden soll, wenn das Programm als Skript von der Konsole aufgerufen wird.So können wir später weiteren Code zu dieser Funktion hinzufügen.
Dann haben wir diese Funktion
main()in den folgenden Hauptblock eingefügt.Und da es eine einzige Funktion ist, könnten andere Python-Dateien sie importieren und direkt aufrufen.
-
In dieser
main()-Funktion erstellen wir auch die Datenbank und die Tabellen.In der vorherigen Version wurde diese Funktion direkt im Hauptblock aufgerufen.
Aber jetzt wird sie nur in der
main()-Funktion aufgerufen. -
Und jetzt erstellen wir auch die Helden in dieser
main()-Funktion. -
Wir haben immer noch einen Hauptblock, um Code auszuführen, wenn das Programm als Skript von der Kommandozeile ausgeführt wird, wie z.B.
$ python app.py // Do whatever is in the main block 🚀 -
Es gibt jetzt eine einzige
main()-Funktion, die den gesamten Code enthält, der ausgeführt werden soll, wenn das Programm von der Konsole aus ausgeführt wird.Das ist also alles, was wir im Hauptblock benötigen. Rufen Sie einfach die
main()-Funktion auf.
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
sqlite_file_name = "database.db"
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def create_heroes(): # (1)!
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") # (2)!
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48)
with Session(engine) as session: # (3)!
session.add(hero_1) # (4)!
session.add(hero_2)
session.add(hero_3)
session.commit() # (5)!
# (6)!
def main(): # (7)!
create_db_and_tables() # (8)!
create_heroes() # (9)!
if __name__ == "__main__": # (10)!
main() # (11)!
-
Wir verwenden eine Funktion
create_heroes(), um diese Logik zusammenzufassen. -
Erstellen Sie jedes der Objekte/Instanzen des
Hero-Modells.Jedes von ihnen repräsentiert die Daten für eine Zeile.
-
Verwenden Sie einen
with-Block, um eineSessionmit derenginezu erstellen.Die neue Session wird der Variablen
sessionzugewiesen.Und sie wird automatisch geschlossen, wenn der
with-Block beendet ist. -
Fügen Sie jedes der Objekte/Instanzen zur Session hinzu.
Jedes dieser Objekte repräsentiert eine Zeile in der Datenbank.
Sie warten dort alle in der Session darauf, gespeichert zu werden.
-
Commiten Sie die Änderungen an die Datenbank.
Dies sendet tatsächlich die Daten an die Datenbank.
Es wird automatisch eine Transaktion gestartet und alle Daten in einem einzigen Batch gespeichert.
-
Zu diesem Zeitpunkt, nachdem der
with-Block beendet ist, ist die Session automatisch geschlossen. -
Wir haben eine
main()-Funktion mit dem gesamten Code, der ausgeführt werden soll, wenn das Programm als Skript von der Konsole aufgerufen wird.So können wir später weiteren Code zu dieser Funktion hinzufügen.
Dann haben wir diese Funktion
main()in den folgenden Hauptblock eingefügt.Und da es eine einzige Funktion ist, könnten andere Python-Dateien sie importieren und direkt aufrufen.
-
In dieser
main()-Funktion erstellen wir auch die Datenbank und die Tabellen.In der vorherigen Version wurde diese Funktion direkt im Hauptblock aufgerufen.
Aber jetzt wird sie nur in der
main()-Funktion aufgerufen. -
Und jetzt erstellen wir auch die Helden in dieser
main()-Funktion. -
Wir haben immer noch einen Hauptblock, um Code auszuführen, wenn das Programm als Skript von der Kommandozeile ausgeführt wird, wie z.B.
$ python app.py // Do whatever is in the main block 🚀 -
Es gibt jetzt eine einzige
main()-Funktion, die den gesamten Code enthält, der ausgeführt werden soll, wenn das Programm von der Konsole aus ausgeführt wird.Das ist also alles, was wir im Hauptblock benötigen. Rufen Sie einfach die
main()-Funktion auf.
Tipp
Überprüfen Sie, was jede Zeile tut, indem Sie auf jede Nummerierung in der Codeübersicht klicken. 👆
Sie können das jetzt in eine app.py-Datei einfügen und mit Python ausführen. Und Sie sehen eine Ausgabe ähnlich der oben gezeigten.
Danach, wenn Sie die Datenbank mit DB Browser for SQLite öffnen, sehen Sie die von Ihnen erstellten Daten im Reiter Browse Data.

Wie geht es weiter¶
Jetzt wissen Sie, wie Sie Zeilen zur Datenbank hinzufügen. 🎉
Jetzt ist ein guter Zeitpunkt, um besser zu verstehen, warum das id-Feld in der Datenbank nicht NULL sein kann, da es ein Primärschlüssel ist, aber im Python-Code tatsächlich None sein kann.
Das erzähle ich Ihnen im nächsten Kapitel. 🚀