Zurück zum Katalog
Season 9 20 Episoden 1h 16m 2026

Pydantic: Data Validation

v2.12 — 2026 Edition. Ein tiefer Einblick in Pydantic v2.12, die am weitesten verbreitete Datenvalidierungsbibliothek für Python, von der grundlegenden Nutzung bis hin zu fortgeschrittenen Funktionen wie Custom Core Schemas und Logfire Observability.

Datenvalidierung Python Core
Pydantic: Data Validation
Aktuelle Wiedergabe
Click play to start
0:00
0:00
1
Die Pydantic-Philosophie: Type Hints als Validierung
Diese Episode stellt die Grundprämisse von Pydantic vor. Du wirst lernen, wie Python Type Hints genutzt werden können, um Schemas zu erzwingen, und wie der Rust-Core für enorme Leistungssteigerungen sorgt.
3m 33s
2
Die Anatomie eines BaseModel
Tauche ein in das BaseModel, die grundlegende Abstraktion von Pydantic. Du wirst lernen, wie die Instanziierung Daten validiert, wie Felder umgewandelt werden und wie Validierungsfehler ausgegeben werden.
3m 52s
3
Field Constraints und das Annotated-Pattern
Lerne, wie du Grenzen über einfache Typen hinaus erzwingst. Du wirst entdecken, wie du die Field-Funktion und das Annotated-Typing-Konstrukt verwendest, um Constraints wie Minima und maximale Längen hinzuzufügen.
4m 25s
4
Field Aliases für Validierung und Serialisierung
Löse den Konflikt der Namenskonventionen zwischen externen APIs und internem Python-Code. Du wirst lernen, wie du deine Python-Attributnamen mithilfe von Validierungs- und Serialisierungs-Aliases von JSON-Keys entkoppelst.
4m 00s
5
Data Coercion vs. Strict Mode
Übernimm die Kontrolle über Pydantics Eifer, Daten umzuwandeln. Du wirst lernen, wie du exakte Typübereinstimmungen erzwingst, indem du den Strict Mode auf Field- oder Model-Ebene aktivierst.
4m 04s
6
Real-World Observability mit Logfire
Bringe Transparenz in deine Daten-Pipelines. Du wirst lernen, wie du Pydantic mit Logfire integrierst, um erfolgreiche und fehlgeschlagene Validierungen in Echtzeit zu überwachen.
3m 55s
7
Beliebige Typen validieren mit TypeAdapter
Lerne, wie du eigenständige Primitiven und Listen validierst, ohne ein BaseModel zu erstellen. Du wirst entdecken, wie der TypeAdapter jeden beliebigen Python-Typ in ein vollwertiges Validierungsziel verwandelt.
4m 19s
8
Union Types und Smart Validation
Verstehe die Komplexität der Validierung von Union Types. Du wirst lernen, wie der Smart Mode von Pydantic Exaktheit und gültige Felder bewertet, um die beste Übereinstimmung auszuwählen.
3m 44s
9
Power-Tool: Discriminated Unions
Optimiere deine Validierungsleistung. Du wirst lernen, wie du Discriminated (Tagged) Unions verwendest, um Pydantic basierend auf einem bestimmten Feld genau mitzuteilen, welches Schema angewendet werden soll.
3m 43s
10
Pre-Processing mit Before und Wrap Validators
Behandle unsaubere eingehende Daten, bevor sie auf dein Schema treffen. Du wirst lernen, wie du Before und Wrap Field Validators verwendest, um rohe Eingaben zu bereinigen, bevor Pydantic sie auswertet.
4m 15s
11
Post-Processing mit After und Plain Validators
Erzwinge strikte Geschäftslogik-Regeln. Du wirst lernen, wie du After Validators verwendest, um bereits geparste Daten zu überprüfen, und Plain Validators, um Pydantic komplett zu umgehen.
3m 47s
12
Model-Level Validation Hooks
Validiere Interaktionen über mehrere Felder hinweg. Du wirst lernen, wie du den model_validator-Decorator verwendest, um Regeln zu erzwingen, die von der gesamten Payload abhängen.
3m 27s
13
Serialisierung: Daten sicher ausgeben (Dumping)
Kontrolliere, wie deine Daten das System verlassen. Du wirst die Unterschiede zwischen dem Dumping in Python-Dicts und JSON-Strings kennenlernen und erfahren, wie du nicht gesetzte oder Standardfelder ausschließt.
3m 46s
14
Serialisierungslogik anpassen
Ändere, wie deine Typen bei der Ausgabe dargestellt werden. Du wirst lernen, wie du benutzerdefinierte Field und Model Serializers schreibst, um Daten während der Dumping-Phase zu verändern.
3m 32s
15
JSON Schema aus Models generieren
Verwandle deine Models in selbstdokumentierende API-Verträge. Du wirst lernen, wie du OpenAPI-konforme JSON Schemas generierst und Beispiele direkt in das Schema injizierst.
3m 11s
16
RootModel: Wenn deine Payload kein Dictionary ist
Behandle nicht standardmäßige JSON-Payloads elegant. Du wirst entdecken, wie RootModel es dir ermöglicht, Arrays und Primitiven auf Root-Ebene zu parsen, während die Fähigkeiten des BaseModel erhalten bleiben.
3m 32s
17
Standard Dataclasses vs. Pydantic Dataclasses
Bringe Validierung in deine nativen Python-Klassen. Du wirst lernen, wann du den Pydantic dataclass-Decorator verwenden solltest, um Legacy-Codebasen nachzurüsten, ohne alles neu schreiben zu müssen.
4m 01s
18
Feinabstimmung der Model Configuration
Kontrolliere die Striktheit deines gesamten Models. Du wirst lernen, wie du das ConfigDict verwendest, um zusätzliche Attribute zu verbieten, Instanzen einzufrieren und Zuweisungen zu validieren.
3m 44s
19
Application Configuration mit Pydantic Settings
Verwalte deine Umgebungsvariablen wie ein Profi. Du wirst lernen, wie das pydantic-settings-Paket das Parsen von Secrets, Dot-Env-Dateien und Präfixen automatisiert.
3m 43s
20
Unter der Haube: Custom Core Schemas
Dies ist die letzte Episode der Serie! Übernimm die ultimative Kontrolle über die Validierungs-Engine. Du wirst lernen, wie du eine __get_pydantic_core_schema__-Methode schreibst, um dem Rust-Core beizubringen, wie er mit völlig fremden Python-Objekten umgeht.
3m 34s

Episoden

1

Die Pydantic-Philosophie: Type Hints als Validierung

3m 33s

Diese Episode stellt die Grundprämisse von Pydantic vor. Du wirst lernen, wie Python Type Hints genutzt werden können, um Schemas zu erzwingen, und wie der Rust-Core für enorme Leistungssteigerungen sorgt.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 1 von 20. Die meisten Data-Validation-Libraries zwingen dich, eine komplett neue domänenspezifische Sprache zu lernen, nur um ein Schema zu definieren. Was aber, wenn die integrierte Syntax von Python schon ausreichen würde, um deine Regeln durchzusetzen? Die Pydantic-Philosophie: Type Hints als Validation löst genau dieses Problem. Bevor wir uns ansehen, wie das funktioniert, müssen wir ein häufiges Missverständnis ausräumen. Pydantic ist kein statischer Type Checker wie mypy. Mypy analysiert deinen Source Code vor der Ausführung, um Logikfehler zu finden. Pydantic arbeitet zur Runtime. Es nimmt nicht vertrauenswürdige Daten von außen, wie zum Beispiel einen JSON-Payload aus einem API-Request, und zwingt sie, den von dir definierten Typen zu entsprechen – und zwar genau dann, wenn dein Programm ausgeführt wird. Die Kernphilosophie hierbei ist Einfachheit. Du definierst ein Datenmodell mit Standard-Python-Type-Annotations. Du erstellst eine Klasse, die einen User repräsentiert, und legst fest, dass die User-ID ein Integer und das Signup-Date ein Datetime-Objekt ist. Das ist dein komplettes Schema. Du schreibst keine eigenen Validation-Funktionen und importierst keine proprietären Field-Types. Wenn ein unstrukturiertes Dictionary von einem Webformular reinkommt, übergibst du es einfach an deine Klasse. Pydantic fängt es ab und garantiert, dass das resultierende Objekt sich strikt an diese Typen hält. Hier ist die wichtigste Erkenntnis: Pydantic ist im Grunde eine Parsing-Library, nicht nur ein striktes Validation-Gate. Wenn ein User ein Webformular abschickt, bei dem die User-ID der String zweiundvierzig ist, erkennt Pydantic, dass dein Modell einen Integer erwartet. Es konvertiert diesen String automatisch in einen nativen Python-Integer. Es versucht, die Daten an dein Schema anzupassen, bevor ein Error geworfen wird. Das übernimmt die nervige Data Coercion, sodass du nicht für jedes Input-Field manuelle Parsing-Logik schreiben musst. Jedes einzelne eingehende Datenelement zur Runtime zu validieren und zu konvertieren, klingt von Natur aus langsam, besonders in Python. Um das zu lösen, läuft die Execution-Logik gar nicht wirklich in Python. Pydantic delegiert die schwere Arbeit an eine dedizierte Core-Engine, die komplett in Rust geschrieben ist. Dieses Design gibt dir die schnelle Developer Experience von purem Python, kombiniert mit der rohen Execution-Speed von kompiliertem System-Code. Stell dir einen Background-Task vor, der ein riesiges JSON-File parst, in dem jeder Record eine Webadresse enthält. Wenn du puren Python-Code schreibst, um durch Tausende von Dictionaries zu loopen, jeden String zu extrahieren, eine Regular-Expression-Library zu laden und zu verifizieren, dass jeder String eine gültige URL ist, wird dein Prozess im Schneckentempo kriechen. Pydantic erledigt das nahtlos. Du annotierst das Address-Field einfach als URL-Type und fütterst dein Modell mit dem rohen JSON. Die Rust-Engine rast durch den Text, parst und validiert die Formate mit einer Geschwindigkeit, an die natives Python nicht herankommt. Die wahre Stärke dieses Ansatzes ist, dass das Autocomplete deines Editors, deine Static-Analysis-Tools und deine Runtime-Validation alle exakt dieselbe Source of Truth teilen, nämlich deine Standard-Type-Hints. Wenn du diese Episoden nützlich findest und die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
2

Die Anatomie eines BaseModel

3m 52s

Tauche ein in das BaseModel, die grundlegende Abstraktion von Pydantic. Du wirst lernen, wie die Instanziierung Daten validiert, wie Felder umgewandelt werden und wie Validierungsfehler ausgegeben werden.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 2 von 20. Wir sprechen oft über Datenvalidierung, aber wenn du dir Pydantic genauer ansiehst, ist das eigentliche Hauptziel Coercion. Es garantiert die Struktur deines Outputs, nicht deines Inputs. Die Anatomie eines BaseModels macht diese Unterscheidung möglich. Die BaseModel-Klasse ist die Grundlage von Pydantic. Um ein Schema zu definieren, erstellst du eine Standard-Python-Klasse und erbst von BaseModel. Sobald du das machst, transformiert Pydantic deine Klasse in einen strikten Data Container. Du definierst die Struktur deiner Daten mit Standard-Python Type Hints. Du brauchst keine proprietären Funktionen, um einen String oder eine Zahl zu deklarieren. Du schreibst einfach den Attributnamen, einen Doppelpunkt und den erwarteten Python-Typ. Stell dir ein User-Model vor. Innerhalb der Klasse definierst du ein einzelnes Feld namens id und typisierst es als Integer. Du könntest auch ein name-Feld hinzufügen, das als String typisiert ist. Das ist die gesamte Definition. Hier ist die entscheidende Erkenntnis. Die eigentliche Arbeit passiert in dem Moment, in dem du das Model instanziierst. Du erstellst eine Instanz, indem du deine Daten als Keyword Arguments übergibst, die genau den definierten Feldnamen entsprechen. Wenn du das tust, fängt Pydantic die Daten ab, bevor das Objekt vollständig initialisiert ist. Es vergleicht die eingehenden Werte mit deinen Type Hints. Genau hier passiert die Coercion. Wenn du den Integer eins-zwei-drei in das id-Feld übergibst, akzeptiert Pydantic ihn sofort. Aber nimm mal an, du empfängst Daten aus einem Web Request oder einer Textdatei und übergibst den String "123" in genau dasselbe Feld. Pydantic wirft nicht sofort einen Error. Es erkennt, dass der Zieltyp ein Integer ist, und versucht, den String zu konvertieren. Weil die Zeichen sicher in eine Zahl gecastet werden können, führt Pydantic die Konvertierung stillschweigend durch. Das Objekt wird erstellt, und das id-Feld speichert einen echten Python-Integer, keinen String. Dieses Verhalten beweist, dass Pydantic im Wesentlichen eine Parsing-Library ist. Sie transformiert eingehende Daten so, dass sie in das strikte Schema passen, das du definiert hast. Natürlich hat diese Konvertierung logische Grenzen. Wenn du das User-Model instanziierst und den String "not an int" an das id-Feld übergibst, versucht Pydantic die Konvertierung und schlägt fehl. Wenn eine Coercion unmöglich ist, wirft Pydantic einen ValidationError. Dieser Error stoppt die Ausführung sofort. Ein entscheidendes Detail beim ValidationError ist, dass Pydantic alle Felder evaluiert, bevor er geworfen wird. Wenn dein Model mehrere Felder mit ungültigen Daten hat, enthält die Exception die Details zu allen Fehlern, anstatt beim allerersten Fehler anzuhalten. Der Error zeigt genau die Felder, die das Problem verursacht haben, die spezifisch übergebenen Werte und die Gründe, warum das Parsen fehlgeschlagen ist. Sobald deine Daten die Instanziierung erfolgreich durchlaufen haben, entspricht das resultierende Objekt garantiert deinen Type Hints. Du greifst auf die Daten genau wie bei jedem Standard-Python-Objekt zu, indem du die Dot Notation verwendest. Wenn du die Instanz einer Variable namens user zugewiesen hast, tippst du einfach user dot id, um den Integer abzurufen. Es sind keine Getter- oder Setter-Methoden erforderlich. Du interagierst mit einem sauberen, strongly typed Objekt. Der wahre Wert der Vererbung von BaseModel liegt nicht nur darin, dass es schlechte Inputs ablehnt, sondern dass es unvorhersehbare externe Daten sicher in einen hochgradig vorhersagbaren internen State normalisiert. Danke fürs Zuhören. Macht's gut zusammen.
3

Field Constraints und das Annotated-Pattern

4m 25s

Lerne, wie du Grenzen über einfache Typen hinaus erzwingst. Du wirst entdecken, wie du die Field-Funktion und das Annotated-Typing-Konstrukt verwendest, um Constraints wie Minima und maximale Längen hinzuzufügen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Datenvalidierung, Folge 3 von 20. Standard Type Hints sagen dir, dass ein Field ein Integer ist, aber sie können dir nicht sagen, dass es größer als null sein muss. Wenn ein negatives Alter oder ein Username mit zehntausend Zeichen durch deine Application Boundaries rutscht, reicht einfaches Type Checking nicht mehr aus, um dein Backend zu schützen. Um strikte Boundaries für deine Daten zu erzwingen, brauchst du Field Constraints und das Annotated Pattern. In Pydantic erlauben dir Constraints, die zulässigen Werte für einen bestimmten Type einzuschränken. Anstatt für jede kleine Regel Custom Validator Functions zu schreiben, kannst du mathematische oder strukturelle Boundaries direkt am Field definieren. Für numerische Typen kannst du mit Parametern wie g-t und l-t Greater-than- oder Less-than-Bounds erzwingen. Für Strings kannst du die Größe des Inputs mit max length und min length beschränken. Um diese Regeln anzuwenden, bietet Pydantic eine Utility Function namens Field. Der traditionelle Weg, wie Developer diese Constraints angewendet haben, war, einen Field Function Call als Default Value eines Model Attributes zuzuweisen. Zum Beispiel würdest du ein age Attribute deklarieren, es als Integer type-hinten und es gleich Field setzen, wobei du g-t gleich null übergibst. Diese Struktur funktioniert, aber sie bringt Friction mit sich. Wenn du einen positiven Integer in fünfzehn verschiedenen Models brauchst, schreibst du genau dieselbe Field-Zuweisung fünfzehn Mal. Noch schlimmer: Weil die Field Function den Slot für die Default Value Zuweisung im Model belegt, macht es die Dinge kompliziert, wenn du diesem Attribute tatsächlich einen echten Default Integer zuweisen willst. Hier ist der springende Punkt. Du musst deine Validation Rules überhaupt nicht an die Attribute-Zuweisung binden. Du kannst sie direkt in die Type Definition selbst einbauen, indem du Pythons typing dot Annotated nutzt. Annotated ist ein Standard Library Feature, mit dem du beliebige Metadata an einen Base Type Hint anhängen kannst. Pydantic ist speziell dafür designt, in einen Annotated Type hineinzuschauen, alle Field Functions zu finden, die du übergeben hast, und ihre Validation Rules automatisch zu extrahieren. Wenn du Annotated benutzt, übergibst du zwei verschiedene Informationen. Erstens übergibst du den Base Python Type, wie einen Integer oder einen String. Zweitens übergibst du die Metadata, was in unserem Fall die Pydantic Field Function ist, die deine Constraints enthält. Lass uns einen wiederverwendbaren age Type bauen, um zu sehen, wie das abläuft. Du definierst eine neue Variable in deinem Code namens PositiveInt. Du weist sie Annotated zu. Innerhalb von Annotated übergibst du integer als Base Type, gefolgt von einem Komma, und dann die Field Function mit g-t gleich null. Du hast gerade ein custom, wiederverwendbares Type Constraint erstellt. Wann immer du jetzt ein User Model oder ein Employee Model definierst, type-hintest du dein age Field einfach mit PositiveInt. Du musst die Field Function nicht mehr auf dem Model Attribute aufrufen. Dieser Ansatz trennt deine Type Definitions von deinen Model Structures. Deine Models bleiben unglaublich clean und lesen sich wie Standard-Python-Klassen ohne Clutter. Wenn sich deine Business Logic später ändert und du plötzlich ein age Field brauchst, das größer als achtzehn statt null ist, updatest du die PositiveInt Definition an genau einer Stelle. Dieses geupdatete Constraint kaskadiert sofort zu jedem Model, das es verwendet. Außerdem, weil Annotated ein natives Python Feature ist, verstehen Static Type Checker perfekt, dass dein custom PositiveInt letztendlich als Standard-Integer evaluiert wird. Durch das Entkoppeln der Validation Metadata vom Default Value Slot transformiert das Annotated Pattern Field Constraints von repetitivem Boilerplate in eine Shared Library aus strikten, wiederverwendbaren Domain Types. Danke, dass du ein paar Minuten mit mir verbracht hast. Bis zum nächsten Mal, mach's gut.
4

Field Aliases für Validierung und Serialisierung

4m 00s

Löse den Konflikt der Namenskonventionen zwischen externen APIs und internem Python-Code. Du wirst lernen, wie du deine Python-Attributnamen mithilfe von Validierungs- und Serialisierungs-Aliases von JSON-Keys entkoppelst.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 4 von 20. Musstest du schon einmal eine Python-Variable in Camel Case benennen, nur um einen externen API-Payload zu parsen? Du weißt, dass das gegen die Standard-Namenskonventionen von Python verstößt, aber das eingehende JSON gibt den Key vor. Die Lösung dafür sind Field Aliases für Validation und Serialization. Wenn du Daten einliest, passen die Keys in diesem Payload oft nicht dazu, wie du deinen Python-Code strukturieren willst. Wenn ein Third-Party-Service ein User-Profil mit dem Key user großes N name sendet, willst du das auf eine Standard-Snake-Case-Variable namens user Unterstrich name mappen. Pydantic übernimmt diesen Translation Layer mit der Field-Funktion, genauer gesagt durch ihre Alias-Argumente. Der einfachste Ansatz ist das Base-Alias-Argument. Wenn du dein Model-Attribut deklarierst, weist du ihm ein Field zu und setzt den Alias-Parameter auf den String, der von der Außenwelt erwartet wird. Wenn du den Alias auf die Camel-Case-Version setzt, verwendet Pydantic genau diesen String sowohl zum Lesen als auch zum Schreiben. Beim Validieren eingehender Daten sucht es nach dem Camel-Case-Key. Wenn du das Model später serialisierst, um es wieder als JSON zu dumpen, schreibt es den Camel-Case-Key. Dein interner Python-Code arbeitet komplett mit dem Snake-Case-Attribut, völlig isoliert von der externen Naming Convention. Das deckt symmetrische Daten ab, bei denen Input-Format und Output-Format identisch sind. Der zweite Teil davon sind asymmetrische Daten. Was passiert, wenn du Daten aus einem Legacy-System mit einer bestimmten Naming Convention konsumierst, sie aber an einen neuen Client mit einer anderen ausliefern musst? Hier teilst du die Logik mit Validation Aliases und Serialization Aliases auf. Das sind separate Argumente, die du der Field-Funktion übergibst. Ein Validation Alias gibt strikt vor, wonach Pydantic beim Erstellen des Models sucht. Wenn du einen Validation Alias übergibst, nutzt Pydantic ihn, um den Wert aus dem eingehenden Payload zu ziehen, und überschreibt dabei jeden Base Alias, den du vielleicht gesetzt hast. Umgekehrt steuert ein Serialization Alias nur die Output-Phase. Wenn du eine Methode aufrufst, um das Model in ein Dictionary oder einen JSON-String zu dumpen, verwendet Pydantic den Serialization Alias als Output-Key. Hier ist die wichtigste Erkenntnis. Du kannst ein einzelnes Field mit drei verschiedenen Identitäten definieren. Der Validation Alias fängt den unsauberen Input-String von der Legacy-API ab. Das Python-Attribut hält die saubere Snake-Case-Variable, die du in deiner Business-Logik verwendest. Und schließlich definiert der Serialization Alias den polierten, standardisierten Key, der an dein Frontend gesendet wird. Manchmal ist das Problem keine starre Naming Convention, sondern eine inkonsistente. Du erhältst vielleicht Payloads, bei denen der User-Identifier mal Camel Case ist und mal ein einzelnes Wort ohne Leerzeichen. Um das zu handhaben, bietet Pydantic ein Utility namens Alias Choices. Anstatt einen einzelnen String an den Validation Alias zu übergeben, übergibst du dieses Utility, das eine Liste von Strings enthält. Während der Validation durchsucht Pydantic den eingehenden Payload nach jedem String in der Reihenfolge, die du angegeben hast. In dem Moment, in dem es einen passenden Key findet, extrahiert es den Wert, weist ihn deinem Python-Attribut zu und ignoriert den Rest. Indem sie trennen, wie Daten geparst und wie sie exportiert werden, entkoppeln Aliases dein internes Python-Objekt-Design von den willkürlichen Naming Constraints der Außenwelt. Das war's für diese Folge. Danke fürs Zuhören, und keep building!
5

Data Coercion vs. Strict Mode

4m 04s

Übernimm die Kontrolle über Pydantics Eifer, Daten umzuwandeln. Du wirst lernen, wie du exakte Typübereinstimmungen erzwingst, indem du den Strict Mode auf Field- oder Model-Ebene aktivierst.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 5 von 20. Pydantics Eifer, den String „123“ in einen Integer zu verwandeln, ist ein Killer-Feature – bis es unbemerkt einen Data-Type-Bug in deinem JSON-Payload versteckt. Du erwartest Zahlen, bekommst aber Strings, und deine Application läuft fröhlich weiter, bis ein striktes Downstream-System abstürzt. Der Mechanismus, der dieses Verhalten steuert, ist Data Coercion, und um das zu bändigen, musst du den Strict Mode verstehen. Standardmäßig arbeitet Pydantic in dem, was die Dokumentation den Lax Mode nennt. In diesem Modus agiert Pydantic eher als Data Parser und nicht nur als Type Checker. Es versucht aktiv, eingehende Daten zu coercen, also in den Typ zu konvertieren, den du deklariert hast. Wenn du ein Field als Integer definierst und der Input-Payload den String „123“ liefert, evaluiert Pydantic den String, extrahiert die gültige Zahl und wandelt sie in einen echten Integer um. Dieses Verhalten ist unglaublich nützlich, wenn du User-Input aus Web-Forms oder Query-Parametern verarbeitest, wo jeder eingehende Wert im Grunde ein String ist. Wenn du jedoch Machine-to-Machine-APIs baust, ist diese stille Conversion oft gefährlich. Wenn ein Client verspricht, einen Integer zu senden, aber stattdessen einen String schickt, bricht er den API-Contract. Der Lax Mode vertuscht diese Verletzung. Hier kommt der Strict Mode ins Spiel. Der Strict Mode deaktiviert die automatische Type Coercion. Wenn du ihn aktivierst, verlangt Pydantic, dass der eingehende Datentyp exakt mit deiner Type Annotation übereinstimmt. Übergib den String „123“ an ein striktes Integer-Field, und Pydantic lehnt ihn sofort mit einem Validation Error ab. Es zwingt die Data Source, das Schema zu respektieren. Du hast zwei Möglichkeiten, den Strict Mode anzuwenden: global über ein Model hinweg oder lokal auf bestimmten Fields. Um ihn global zu erzwingen, passt du die Model Configuration an. Indem du das strict Configuration Flag auf true setzt, hört jedes einzelne Field in diesem Model auf, Typen zu coercen. Ein Boolean-Field akzeptiert nur einen true oder false Boolean-Wert, nicht den String „true“ oder den Integer eins. Ein Integer-Field akzeptiert nur Integers. Hier ist der entscheidende Punkt: Globale Strictness ist oft zu starr für Real-World-Applications, bei denen Daten aus gemischten Quellen eintreffen. Normalerweise willst du ein paar kritische Identifier absichern, während du den Rest des Models flexibel lässt. Um das zu erreichen, erlaubt Pydantic lokale Strictness. Du kannst den Strict Mode für ein einzelnes Field erzwingen, indem du spezielle Types verwendest, die von der Library bereitgestellt werden, wie StrictInt, StrictStr oder StrictBool. Wenn du ein User-ID-Field mit StrictInt definierst, lehnt dieses spezifische Field String-Repräsentationen von Zahlen ab, während der Rest deines Models weiterhin im Lax Mode arbeitet. Du kannst das auch erreichen, indem du ein strict Flag direkt an die Field Definition Function für jeden Standard-Typ übergibst. Stell dir einen Service vor, der einen JSON-Payload für eine Finanztransaktion verarbeitet. Der Payload enthält eine Account-ID. Wenn sie als normaler Integer definiert ist, geht ein Payload, der die Account-ID als String „123“ liefert, einfach durch. Pydantic fixt den Datentyp im Memory. Wenn du dieses Field auf StrictInt updatest, schlägt genau derselbe JSON-Payload bei der Validation fehl. Der Client erhält einen expliziten Error, der besagt, dass der Input ein valider Integer sein muss, und fängt so die Contract Violation an der System Boundary ab, bevor sie deine Datenbank verschmutzt. Der Strict Mode verwandelt Pydantic von einem hilfreichen Parser, der unordentliche Inputs bereinigt, in einen rigiden Enforcer, der Data Contracts garantiert. Danke fürs Zuhören. Macht's gut, zusammen.
6

Real-World Observability mit Logfire

3m 55s

Bringe Transparenz in deine Daten-Pipelines. Du wirst lernen, wie du Pydantic mit Logfire integrierst, um erfolgreiche und fehlgeschlagene Validierungen in Echtzeit zu überwachen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 6 von 20. Wenn ein komplexer Payload in Production die Validierung nicht besteht, verrät der Standard Stack Trace allein selten genau, warum die Daten abgelehnt wurden. Du weißt zwar, dass ein Request fehlgeschlagen ist, aber du bist komplett blind für die tatsächlichen eingehenden Werte, die den Crash verursacht haben. Genau dieses Problem löst Real-World Observability mit Logfire. Logfire ist eine Observability Plattform, die vom Pydantic Team entwickelt wurde, und sie bietet eine direkte Integration mit Pydantic selbst. Ziel ist es, dir Einblick zu geben, was dein Data Validation Layer in Production eigentlich genau macht. Anstatt die Validierung als Black Box zu behandeln, die gelegentlich Exceptions wirft, verwandelt diese Integration jeden Validierungs-Check in getrackte Telemetrie. Stell dir einen Background Worker vor, der User Signups aus einer Message Queue verarbeitet. Hunderte von Events kommen pro Sekunde an. Plötzlich schlägt ein Signup mit einem Validation Error fehl. Ohne die richtige Instrumentierung zeigen deine Logs nur einen generischen Crash. Du musst den rohen Queue Payload durchsuchen, um herauszufinden, dass der User ein Alter von minus fünf angegeben hat. Um das zu beheben, importierst du das Logfire Package und rufst eine einzige Funktion namens instrument underscore pydantic auf. Das platzierst du direkt nach der Initialisierung deines Logfire Clients. Ab diesem Moment sind deine Pydantic Models vollständig observable. Du musst nicht ändern, wie du deine Models definierst oder wie du sie instanziierst. Hier ist der entscheidende Punkt. Sobald sie instrumentiert sind, erstellt Logfire jedes Mal, wenn Pydantic Daten validiert, automatisch einen Span. Ein Span ist einfach eine zeitlich erfasste Aufzeichnung einer Operation. Wenn der Signup Payload absolut gültig ist, zeichnet Logfire einen erfolgreichen Span auf, der genau zeigt, wie lange die Validierung gedauert hat. Das ist extrem nützlich, wenn du komplexe Custom Validators hast und Performance Bottlenecks überwachen musst. Wenn der Payload ungültig ist, wirft Pydantic einen Validation Error. Logfire fängt dieses Event ab und hängt die Details an den Trace an. Es erfasst das spezifische Model, das involviert ist, und die genauen Fields, die den Fehler ausgelöst haben. Wenn du auf dein Observability Dashboard schaust, siehst du nicht nur eine generische Error Message. Du siehst die exakten abgelehnten Werte, wie dieses negative Alter oder einen fehlerhaften Email String. Das Setup ist komplett hands-off. Erstens, konfiguriere den Client. Zweitens, rufe die Instrument-Funktion auf. Drittens, lass deinen Worker Daten verarbeiten. Wenn der Worker versucht, einen fehlerhaften JSON String in dein Signup Model zu parsen, erfasst die Telemetrie den Fehlerkontext automatisch. Du schreibst absolut null Custom Exception Blöcke, um den fehlerhaften Input zu loggen. Weil Logfire Pydantic nativ versteht, respektiert es deine Datenstrukturen. Es kennt den Unterschied zwischen einem fehlenden Field und einem Type Mismatch, und es formatiert diese Telemetrie so, dass du sie später abfragen kannst. Du kannst deine Metrics filtern, um genau herauszufinden, wie oft das Email Field heute in deinem gesamten Worker Cluster die Validierung nicht bestanden hat. Der wahre Wert dieser Integration ist, dass sie Data Validation von einem simplen Code Check zu einem First-Class Observability Event erhebt und stille Datenablehnungen in strukturierte, actionable Telemetrie verwandelt. Wenn du die Show unterstützen möchtest, findest du uns, indem du nach DevStoriesEU auf Patreon suchst. Das war's für diese Folge. Danke fürs Zuhören und keep building!
7

Beliebige Typen validieren mit TypeAdapter

4m 19s

Lerne, wie du eigenständige Primitiven und Listen validierst, ohne ein BaseModel zu erstellen. Du wirst entdecken, wie der TypeAdapter jeden beliebigen Python-Typ in ein vollwertiges Validierungsziel verwandelt.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 7 von 20. Manchmal musst du nur eine einfache Liste von Strings aus einem API Request validieren, aber dafür eine ganze Model Class zu erstellen, nur um diese eine Liste zu halten, fühlt sich nach massivem Overkill an. Du willst kein Wrapper Object, du willst einfach nur die validierte Liste. Die Lösung dafür ist das Validieren beliebiger Typen mit dem TypeAdapter. In Pydantic dreht sich der Standard-Workflow darum, eine Klasse zu definieren, die vom Base Model erbt. Dieses Model gibt dir Zugriff auf mächtige Methoden zum Parsen und Serialisieren von Daten. Aber Pydantic ist absolut in der Lage, Standard-Python-Typen zu validieren, wie ein einfaches Dictionary, einen einzelnen Integer, eine Standard-Dataclass oder ein Typed Dict. Der Haken ist, dass diese Standardtypen nicht von Haus aus Pydantic-Validierungsmethoden besitzen. Du kannst validate nicht auf einer Standard-Python-Liste aufrufen. Hier kommt der TypeAdapter ins Spiel. Er fungiert als Brücke, wrappt jeden beliebigen Python-Typ und stellt alle bekannten Model-Methoden dafür bereit. Stell dir einen Web Endpoint vor, der ein rohes JSON Array von Strings akzeptiert. In der Vergangenheit hättest du vielleicht ein Dummy Model mit einem einzigen Feld namens items erstellt, nur damit du den JSON Payload daran übergeben kannst. Das zwingt den Client, ein JSON Object mit einem items Key zu senden, oder zwingt dich, das validierte Model später zu entpacken. Mit einem TypeAdapter überspringst du das Dummy Model komplett. Zuerst instanziierst du den Adapter und übergibst ihm die exakte Typdefinition, die du erwartest. In diesem Fall übergibst du den Python Type Hint für eine Liste von Strings. Das erstellt ein Adapter Object, das speziell für genau diese Struktur konfiguriert ist. Jetzt hast du Zugriff auf die Standard-Validierungsmethoden. Du nimmst den rohen JSON Payload von deinem Endpoint und übergibst ihn an die validate json Methode deiner Adapter-Instanz. Pydantic parst den rohen Byte String, prüft, ob es ein JSON Array ist, verifiziert, dass jedes Element darin ein String ist, und gibt eine Standard-Python-Liste zurück. Wenn der Payload einen Integer oder einen Boolean enthält, wirft es einen Validation Error, genau wie es ein reguläres Model tun würde. Hier ist der entscheidende Punkt. Der Adapter ist nicht auf einfache Validierung beschränkt. Er spiegelt die Core API eines Standard-Models komplett wider. Das bedeutet, du kannst ihn auch verwenden, um Daten zu serialisieren. Wenn du ein komplexes Dictionary oder eine Standard-Python-Dataclass hast und sie zurück in einen JSON String konvertieren musst, übergibst du diese Daten an die dump json Methode deines Adapters. Er wendet genau dieselben Serialisierungsregeln, Custom Encoders und Formatierungen an, die Pydantic auf reguläre Models anwendet. Dieses Feature ist besonders nützlich, wenn du mit Typed Dicts arbeitest. Ein Typed Dict bietet Structural Typing für Standard-Python-Dictionaries, aber es führt null Runtime Validation durch. Indem du ein Typed Dict an einen Adapter übergibst, bekommst du volle Runtime Enforcement der Dictionary-Struktur. Er stellt sicher, dass alle erforderlichen Keys vorhanden sind und die Values den erwarteten Typen entsprechen, ohne das Dictionary in eine Object Instance zu konvertieren. Der Output bleibt ein einfaches Dictionary. Das Instanziieren eines Adapters erfordert, dass Pydantic interne Validation Schemas baut. Weil dieser Setup-Prozess ein wenig Compute Time beansprucht, solltest du deine Adapter-Instanzen auf Module Level erstellen, anstatt sie jedes Mal innerhalb einer Funktion neu zu bauen, wenn ein Endpoint aufgerufen wird. Definiere den Adapter einmal oben in deinem File und verwende ihn über mehrere Requests hinweg wieder. Der TypeAdapter gibt dir die volle Power der Core Validation Engine für jeden Standard-Python-Typ und hält deine Datenstrukturen sauber und frei von unnötigen Wrapper Classes. Das war's für heute. Danke fürs Zuhören – geh und bau etwas Cooles.
8

Union Types und Smart Validation

3m 44s

Verstehe die Komplexität der Validierung von Union Types. Du wirst lernen, wie der Smart Mode von Pydantic Exaktheit und gültige Felder bewertet, um die beste Übereinstimmung auszuwählen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 8 von 20. Wenn ein Feld als Union aus String oder Integer annotiert ist und du den Integer 123 übergibst, welche Validierung versucht Pydantic dann eigentlich zuerst? Wenn du davon ausgehst, dass es deinen Code einfach von links nach rechts liest, bist du vielleicht überrascht, wenn sich deine Daten anders verhalten als erwartet. Das bringt uns zu Union Types und Smart Validation. Ein Union Type ermöglicht es einem einzelnen Feld, mehrere verschiedene Datentypen zu akzeptieren. Die Validierung von Unions ist von Natur aus komplex, da Pydantic aktiv versucht, Daten in den angeforderten Typ umzuwandeln. Ein Integer kann leicht zu einem String werden, und ein String mit Ziffern kann in einen Integer geparst werden. Würde die Validation Engine einfach den ersten Match nehmen, den sie findet, würde sich deine Ausgabe komplett ändern, nur basierend auf der willkürlichen Reihenfolge, in der du die Typen in deinem Code aufgelistet hast. Dieses starre Verhalten gibt es tatsächlich, und es nennt sich Left to Right Mode. In diesem Modus prüft das System den Input gegen den ersten Typ, der in der Union definiert ist. Wenn die Validierung erfolgreich ist, stoppt es sofort. Schlägt sie fehl, geht es weiter zum zweiten Typ. Wenn dein Feld als String oder Integer getypt ist, in dieser Reihenfolge, und du den Integer 123 übergibst, prüft der Left to Right Mode zuerst die String-Bedingung. Da der Integer 123 nahtlos in den String "123" umgewandelt werden kann, ist die Validierung erfolgreich. Dein Integer wird stillschweigend in einen String konvertiert, nur weil String zuerst da stand. Hier ist der entscheidende Punkt. Standardmäßig vermeidet Pydantic diese Falle, indem es den Smart Mode nutzt. Anstatt beim ersten passablen Match anzuhalten, evaluiert der Smart Mode den Input gegen alle möglichen Typen in der Union. Dann vergleicht er die erfolgreichen Validierungen und wählt den besten Match basierend auf bestimmten Scoring-Kriterien aus. Das Hauptkriterium für einfache Typen ist die Exaktheit. Der Smart Mode bestraft Data Coercion extrem. Gehen wir zurück zu unserem vorherigen Szenario mit einem Feld, das als String oder Integer getypt ist. Wenn du den Integer 123 übergibst, testet der Smart Mode beide Optionen. Er erkennt, dass der Input in einen gültigen String umgewandelt werden kann, aber er sieht auch, dass der Input bereits ein perfekter, exakter Match für einen Integer ist. Weil ein exakter Match immer einen höheren Score erzielt als ein umgewandelter Match, gibt der Smart Mode korrekterweise den Integer 123 zurück, unabhängig davon, welcher Typ in der Union zuerst stand. Wenn deine Union komplexe Data Models statt einfacher Typen enthält, verlässt sich der Smart Mode auf eine andere Metrik. Er zählt die Anzahl der gesetzten gültigen Felder. Die Engine evaluiert das Input-Dictionary gegen jedes Model in der Union. Sie berechnet, wie viele Felder im Input exakt auf die definierten Felder jedes Models mappen. Das Model, das erfolgreich die höchste Anzahl an Input-Feldern aufnimmt, ohne Validation Errors zu werfen, wird zum Gewinner erklärt. Das verhindert, dass ein kleineres, weniger spezifisches Model Daten schluckt, die eindeutig für ein größeres, detaillierteres Model in derselben Union gedacht waren. Smart Validation stellt sicher, dass deine Daten ihre genaue ursprüngliche Form wann immer möglich beibehalten, und schützt dich vor stillen Coercion Errors, die in Production bekanntermaßen schwer aufzuspüren sind. Danke fürs Zuhören, Happy Coding zusammen!
9

Power-Tool: Discriminated Unions

3m 43s

Optimiere deine Validierungsleistung. Du wirst lernen, wie du Discriminated (Tagged) Unions verwendest, um Pydantic basierend auf einem bestimmten Feld genau mitzuteilen, welches Schema angewendet werden soll.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 9 von 20. Einen eingehenden Payload durch Ausprobieren gegen zwanzig verschiedene Datenmodelle zu validieren, ist ein Performance-Albtraum. Wenn dein System ein generisches Event empfängt, verschwendet das Raten, welches Schema angewendet werden soll, CPU-Cycles und erzeugt extrem verwirrende Fehlermeldungen, wenn die Validierung fehlschlägt. Du kannst dieses Ratespiel komplett umgehen, indem du ein Power-Tool nutzt: Discriminated Unions. Eine Standard-Union teilt Pydantic mit, dass ein Feld eines von mehreren verschiedenen Models sein könnte. Standardmäßig nimmt Pydantic die eingehenden Daten und testet sie gegen das erste Model. Wenn das fehlschlägt, probiert es das zweite, und so weiter. Dieses sequentielle Parsing ist ineffizient. Discriminated Unions lösen das durch einen expliziten Tag. Angenommen, du baust eine Analytics-Pipeline, die verschiedene Event-Typen empfängt, wie ein Click-Event, ein Scroll-Event und ein Purchase-Event. Jedes Event erfordert andere Datenfelder. Das Click-Model braucht vielleicht eine Element-ID, während das Purchase-Model einen Transaktionsbetrag benötigt. Um eine Discriminated Union einzurichten, fügst du jedem einzelnen Model in dieser Gruppe ein gemeinsames Feld hinzu. Du könntest dieses Feld Event-Typ nennen. Dann weist du diesem Feld einen Literal String Type zu. Das Click-Model erzwingt, dass der Event-Typ exakt der String click ist. Das Purchase-Model erzwingt strikt den String purchase. Als Nächstes erstellst du dein Haupt-Payload-Model. Dieses Model hat ein einziges Event-Feld, das als Union deiner spezifischen Event-Models definiert ist. Hier konfigurierst du den Discriminator. Du packst die Union-Definition in eine Pydantic Field-Konfiguration und weist dem Discriminator-Argument den String Event-Typ zu. Hier ist der entscheidende Punkt. Wenn ein Payload ankommt, testet Pydantic die Models nicht mehr nacheinander. Es schaut direkt auf den Event-Typ-Key in den eingehenden Daten. Wenn der Wert purchase ist, routet Pydantic den gesamten Payload sofort an das Purchase-Model. Es ist ein direkter Lookup. Wenn der Transaktionsbetrag fehlt, sagt die Fehlermeldung ganz klar, dass ein erforderliches Feld für ein Purchase-Event fehlt, anstatt eine riesige Textwand zu generieren, die erklärt, warum die Daten auf keinen der möglichen Event-Typen gepasst haben. Das deckt eine saubere Struktur ab, bei der jeder Payload einen gemeinsamen Top-Level-Key hat. Manchmal hast du es mit unstrukturierten Third-Party-Daten zu tun, bei denen der identifizierende Tag in einem anderen Objekt verschachtelt ist, oder das richtige Model von der Anwesenheit bestimmter Keys abhängt, statt von einem einzelnen dedizierten Wert. Für diese Situationen bietet Pydantic Callable Discriminators. Anstatt einen String-Feldnamen an das Discriminator-Argument zu übergeben, übergibst du eine Custom-Funktion. Diese Funktion empfängt die rohen, unvalidierten Input-Daten. Du schreibst die Logik in dieser Funktion, um das rohe Dictionary zu untersuchen, den Hinweis zu finden, der den Datentyp bestimmt, und einen einfachen String-Tag zurückzugeben, der das richtige Model repräsentiert. Pydantic führt deine Funktion zuerst aus, bekommt den String-Tag zurück und nutzt ihn, um die Daten an das genaue Model in der Union zu routen. Eine Discriminated Union zu verwenden, verwandelt die Validierung von einem sequentiellen Ratespiel in einen präzisen Constant-Time Lookup. Danke fürs Zuhören, euch allen noch einen schönen Tag!
10

Pre-Processing mit Before und Wrap Validators

4m 15s

Behandle unsaubere eingehende Daten, bevor sie auf dein Schema treffen. Du wirst lernen, wie du Before und Wrap Field Validators verwendest, um rohe Eingaben zu bereinigen, bevor Pydantic sie auswertet.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 10 von 20. Manchmal sind deine eingehenden Daten so unstrukturiert, dass das Standard-Parsing fehlschlägt, sobald sie dein Model berühren. Du musst den Raw Input abfangen und bereinigen, bevor das Framework überhaupt versucht, ihn zu lesen. Genau das ermöglicht dir das Pre-processing mit Before und Wrap Validators. Pydantic leistet normalerweise hervorragende Arbeit dabei, Daten automatisch in den richtigen Type umzuwandeln. Aber wenn die grundlegende Struktur der Daten komplett falsch ist, schlägt die Coercion sofort fehl. Ein Before Validator ist genau für dieses Problem gedacht. Es ist eine Funktion, die an ein Field angehängt ist und ausgeführt wird, bevor Pydantic sein eigenes Type Checking oder Conversion durchführt. Sie erhält den rohen, unberührten Input exakt so, wie er an das Model übergeben wurde. Stell dir ein Szenario vor, in dem dein Model ein Field definiert, das zwingend eine List von Integers erfordert. Du konsumierst jedoch eine externe API, die diese Daten fälschlicherweise als einen einzigen durchgehenden String von Zahlen sendet, die durch Kommas getrennt sind, wie zum Beispiel den String eins Komma zwei Komma drei. Pydantic erwartet ein Array, sieht einen einzelnen String und lehnt ihn mit einem Validation Error ab. Du behebst das, indem du einen Before Validator schreibst. Innerhalb deiner Validator-Funktion schaust du dir den Raw Input an. Du prüfst, ob der Value ein String ist. Wenn das der Fall ist, splittest du diesen String an jedem Komma, was eine Liste von einzelnen String-Zeichen erstellt. Du musst diese Zeichen nicht selbst in Integers umwandeln. Du gibst einfach die neu erstellte Liste zurück. Pydantic übernimmt von da an. Es sieht die Liste, die es erwartet hat, führt seine standardmäßige interne Coercion durch und verwandelt diese String-Values für dich in Integers. Du musstest lediglich die strukturelle Form der Daten fixen. Damit sind Inputs abgedeckt, die vor der Hauptlogik laufen. Die nächste Kontrollebene ist der Wrap Validator. Wrap Validators sind das flexibelste Validation-Tool, das Pydantic bietet. Anstatt nur vor dem Validation-Schritt zu laufen, umschließt ein Wrap Validator buchstäblich Pydantics interne Validation-Engine für dieses Field. Wenn du einen Wrap Validator schreibst, erhält deine Funktion zwei Argumente. Das erste ist der Raw Input, genau wie beim Before Validator. Das zweite Argument ist eine Handler-Funktion. Dieser Handler repräsentiert die Kernlogik von Pydantic für Validation und Coercion. Hier wird es interessant. Du entscheidest genau, wann – oder ob überhaupt – diese Handler-Funktion ausgeführt wird. Der Logic Flow liegt vollständig in deinen Händen. Du kannst den Raw Input untersuchen und modifizieren. Dann rufst du den Handler explizit auf und übergibst ihm deine bereinigten Daten. Pydantic führt sein internes Type Checking mit dem durch, was du bereitgestellt hast, und gibt den vollständig geparsten Value an deinen Validator zurück. Du kannst diesen geparsten Value dann erneut modifizieren, bevor du ihn an das finale Model übergibst. Weil du kontrollierst, wann der Handler ausgeführt wird, kannst du ihn in einen Standard Try-Except-Block packen. Wenn Pydantics interne Validation einen Error wirft, fängst du ihn direkt dort im Wrap Validator ab. Du kannst den Error loggen, die Daten ändern und es erneut versuchen, oder einfach einen sicheren Default Value zurückgeben. Du kannst sogar Logik schreiben, die den Handler für bestimmte spezifische Inputs komplett überspringt und so die Standard-Validation vollständig umgeht. Before Validators bereinigen fehlerhafte Input-Strukturen, damit Pydantic sie lesen kann, während Wrap Validators dir die volle Kontrolle über den gesamten Validation Lifecycle rund um ein einzelnes Field geben. Das war’s für diese Folge. Danke fürs Zuhören, und keep building!
11

Post-Processing mit After und Plain Validators

3m 47s

Erzwinge strikte Geschäftslogik-Regeln. Du wirst lernen, wie du After Validators verwendest, um bereits geparste Daten zu überprüfen, und Plain Validators, um Pydantic komplett zu umgehen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 11 von 20. Zu prüfen, ob ein String dem E-Mail-Format entspricht, ist einfach. Zu überprüfen, ob die Daten strikter Business Logic entsprechen, wie zum Beispiel dem Abgleich mit einem externen System oder der Einhaltung bestimmter mathematischer Regeln, erfordert einen sicheren Ort, um Custom Code auszuführen. Genau das bietet Post-processing mit After und Plain Validators. Wenn du ein Field in einem Pydantic Model definierst, prüft die Library die Eingabe automatisch anhand des Type Hints. Types bringen dich aber nur bis zu einem gewissen Punkt. Ein Integer ist ein Integer, egal ob er eins oder eine Million ist. Um Regeln jenseits der grundlegenden Types durchzusetzen, fügst du Custom Validation Functions hinzu. Pydantic ermöglicht es dir, diese Funktionen in den Validation Lifecycle einzubinden. Der häufigste Injection Point ist der After Validator. Wie der Name schon sagt, wird dieser ausgeführt, nachdem Pydantic sein internes Parsing und die Type Coercion abgeschlossen hat. Hier ist die entscheidende Erkenntnis: Wenn deine Custom Function die Daten in einem After Validator empfängt, garantiert Pydantic, dass die Daten bereits dem Field Type entsprechen. Du musst keinen Boilerplate Code für Type Conversion oder das Abfangen unerwarteter Data Types schreiben. Stell dir ein Szenario vor, in dem du sicherstellen musst, dass ein Integer Field eine gerade Zahl ist. Du definierst ein Model mit einem Field vom Typ Integer. Dann schreibst du eine Custom Function, die einen Value als Argument entgegennimmt. Weil du diese Funktion als After Validator konfigurierst, weißt du, dass der Value definitiv ein Integer ist. Du verwendest einfach den Modulo-Operator, um zu prüfen, ob die Division des Values durch zwei einen Rest ergibt. Ist der Rest ungleich null, löst du einen Standard Python Value Error mit einer Custom Message aus. Ist der Rest null, gibst du den Value zurück. Pydantic nimmt diesen zurückgegebenen Value und weist ihn dem Model zu. Die Arbeitsteilung ist sauber. Pydantic erzwingt den Type, und du erzwingst die Business Rule. Manchmal steht dir das Default Parsing von Pydantic im Weg. Genau da kommt der Plain Validator ins Spiel. Ein Plain Validator ersetzt die interne Validation von Pydantic für ein bestimmtes Field komplett. Pydantic tritt beiseite und übergibt den unvalidierten Raw Input direkt an deine Custom Function. Du verwendest einen Plain Validator, wenn die Standard Coercion Rules nicht zu deinem Use Case passen, oder wenn du es mit einer hochgradig Custom Data Structure zu tun hast, die Pydantic nativ nicht versteht. In diesem Szenario ist deine Funktion für alles verantwortlich. Sie empfängt den Raw Input, führt jegliches notwendige Type Checking durch, konvertiert die Daten und wendet Business Logic an. Wenn etwas fehlschlägt, muss deine Funktion einen Value Error oder einen Assertion Error auslösen. Wenn sie erfolgreich ist, gibt sie den finalen, sauberen Value für das Model zurück. Du hängst diese beiden Validators an Fields an, indem du Pydantic Decorators für Class Methods verwendest, oder indem du sie als Metadata direkt innerhalb des Type Hints mittels Annotations hinzufügst. Die Wahl zwischen den beiden hängt davon ab, wie viel von der Arbeit du selbst übernehmen möchtest. Verwende einen After Validator, wenn du möchtest, dass Pydantic die Schwerstarbeit der Type Conversion übernimmt, und greife nur dann zu einem Plain Validator, wenn du absolute Kontrolle über das Parsing des Raw Inputs von Grund auf brauchst. Danke fürs Zuhören – bis zum nächsten Mal.
12

Model-Level Validation Hooks

3m 27s

Validiere Interaktionen über mehrere Felder hinweg. Du wirst lernen, wie du den model_validator-Decorator verwendest, um Regeln zu erzwingen, die von der gesamten Payload abhängen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Datenvalidierung, Folge 12 von 20. Die Validierung isolierter Felder funktioniert einwandfrei, bis zu dem Moment, in dem deine Business Logic vorschreibt, dass Feld B nur gesetzt werden darf, wenn Feld A einen bestimmten Wert hat. Wenn die Datenintegrität von der Interaktion mehrerer Felder abhängt, brauchst du Model-Level Validation Hooks. In Pydantic behandelst du voneinander abhängige Felder mit dem Model Validator Decorator. Im Gegensatz zu Field Validators, die sich auf ein einzelnes eingehendes Datenelement konzentrieren, betrachtet ein Model Validator die gesamte Datenstruktur auf einmal. Pydantic bietet drei Modi für diesen Decorator: before, after und wrap. Sie legen genau fest, wann deine Custom Logic während des Parsing Lifecycles ausgeführt wird. Lass uns das auf ein typisches User Registration Model anwenden. Du hast zwei Felder: password und password repeat. Ein Field-Level Check kann die Länge oder Komplexität überprüfen, aber er kann die beiden nicht vergleichen. Dafür verwendest du einen Model Validator im after-Modus. Der after-Modus wird ausgeführt, sobald Pydantic alle einzelnen Felder erfolgreich geparst und validiert hat. In dieser Phase erhält deine Validation Function das instanziierte Model selbst. Du schreibst einfach eine Logik, die prüft, ob das password-Attribut des Models mit dem password repeat-Attribut übereinstimmt. Wenn sie sich unterscheiden, wirfst du einen ValueError. Hier ist der entscheidende Punkt. Wenn du den after-Modus verwendest, muss deine Funktion am Ende der Methode die Model-Instanz, meistens als self bezeichnet, explizit zurückgeben. Wenn du vergisst, self zurückzugeben, verwirft Pydantic deine validierten Daten und gibt nichts zurück. Manchmal musst du Daten schon früher abfangen. Da kommt der before-Modus ins Spiel. Ein Model Validator im before-Modus läuft, bevor Pydantic überhaupt ein Parsing oder eine Type Coercion versucht. Anstelle einer typisierten Model-Instanz erhält deine Funktion den Raw Input, was typischerweise ein Dictionary ist. Du nutzt diesen Modus, wenn die rohe Datenstruktur unsauber ist und angepasst werden muss, bevor die Standardvalidierung überhaupt beginnen kann. Wenn zum Beispiel Legacy-API-Requests Passwort-Konfigurationen in einem verschachtelten Dictionary senden, kann ein before-Validator diese Strings extrahieren und sie in die Top-Level Keys flatten, die dein Pydantic-Model erwartet. Die Funktion gibt dann das modifizierte Dictionary zurück und reicht es in der Chain weiter. Der dritte Modus ist wrap. Dieser ist für die absolute Kontrolle über den Validation Lifecycle. Ein wrap-Validator nimmt die rohen Input-Daten und eine Handler-Funktion entgegen. Du führst deine Pre-Processing-Logik aus, rufst den Handler explizit auf, um Pydantics interne Validierung zu triggern, und führst dann ein Post-Processing auf dem Ergebnis aus. Das nutzt du, wenn du interne Pydantic Validation Errors abfangen, sie in einem externen System loggen und vielleicht eine modifizierte Fehlermeldung oder ein Default-Fallback-Objekt zurückgeben musst. Die Wahl des richtigen Modus ist nur eine Frage des Timings. Nutze before, um den Raw Input zu formen, after, um stark typisierte Felder zu vergleichen, und wrap, um die Validation Execution selbst zu kontrollieren. Wenn du diese Episoden hilfreich findest und die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für dieses Mal. Bis zum nächsten Mal!
13

Serialisierung: Daten sicher ausgeben (Dumping)

3m 46s

Kontrolliere, wie deine Daten das System verlassen. Du wirst die Unterschiede zwischen dem Dumping in Python-Dicts und JSON-Strings kennenlernen und erfahren, wie du nicht gesetzte oder Standardfelder ausschließt.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Datenvalidierung, Folge 13 von 20. Gültige Daten in dein System zu bekommen, ist nur die halbe Miete. Wenn es an der Zeit ist, diese Daten an ein Frontend zurückzugeben, stellst du oft fest, dass deine Payloads mit leeren Feldern und Default-Werten aufgebläht sind, die der User nie wirklich angegeben hat. Serialisierung, oder das sichere Dumpen von Daten, ist der Weg, wie du diesen ausgehenden Flow bereinigst. Sobald deine Daten sicher in einem Pydantic-Model liegen, musst du sie irgendwann extrahieren, um sie woandershin zu senden. Dafür hast du zwei primäre Möglichkeiten. Die erste ist der Aufruf von model dump. Diese Methode liest dein Model und gibt ein einfaches Python-Dictionary zurück. Die zweite ist der Aufruf von model dump json. Diese Methode überspringt den Dictionary-Schritt und gibt einen vollständig formatierten JSON-String zurück, der direkt übers Netzwerk gesendet werden kann. Der Unterschied zwischen den beiden geht etwas tiefer als nur Dictionary versus String. Es geht dabei um die Serialization Modes. Standardmäßig arbeitet model dump im Python-Modus. Wenn dein Model einen komplexen Typ wie ein Datetime-Objekt enthält, wird das resultierende Dictionary weiterhin ein Python-Datetime-Objekt enthalten. Auf der anderen Seite arbeitet model dump json im JSON-Modus. JSON weiß nicht, was ein Python-Datetime-Objekt ist, also konvertiert Pydantic es automatisch in eine Standard-String-Repräsentation. Hier ist die entscheidende Erkenntnis. Du kannst die Dictionary-Ausgabe tatsächlich zwingen, den JSON-Modus zu verwenden. Wenn du model dump aufrufst und das mode-Argument auf json setzt, gibt Pydantic ein Dictionary zurück, in dem alle komplexen Typen bereits in einfache, JSON-sichere Formate wie Strings und Integers übersetzt wurden. Damit sind die Typen abgedeckt, aber du musst immer noch die Struktur des Payloads verwalten. Nehmen wir ein User-Profile-Model, das Daten an ein Frontend zurückgibt. Das Model definiert vielleicht zwanzig mögliche Felder. Ein neuer User meldet sich an und gibt nur seinen Namen und seine E-Mail an. Die anderen achtzehn Felder fallen auf leere Strings, Nulls oder Default-Avatar-URLs zurück. Wenn du dieses Model normal dumpst, sendest du alle zwanzig Felder ans Frontend. Um das zu beheben, bietet Pydantic drei spezifische Keyword-Argumente, die du an beide Dump-Methoden übergeben kannst. Das präziseste ist exclude unset. Wenn du exclude unset auf true setzt, trackt Pydantic genau, welche Felder beim Erstellen des Models befüllt wurden. Es dumpt nur den Namen und die E-Mail. Die achtzehn Default-Felder werden komplett aus dem Dictionary oder JSON-String weggelassen. Das stellt sicher, dass du niemals Fallback-Daten leakst, die der User gar nicht wirklich übermittelt hat. Wenn du ein etwas anderes Verhalten möchtest, kannst du exclude defaults verwenden. Dieses Flag sagt Pydantic, dass es jedes Feld auslassen soll, das aktuell seinem Default-Wert entspricht. Dabei ist es egal, ob der User diesen Default-Wert explizit übergeben hat oder ob das System ihn automatisch eingefügt hat. Wenn der Wert dem Default entspricht, wird er aus dem Output entfernt. Schließlich gibt es noch exclude none. Setze das auf true, und Pydantic entfernt jedes Feld, dessen Wert aktuell none ist. Das ist eine reine Value-Prüfung und ignoriert Defaults oder Unset-Tracking komplett. Diese Exclusion-Flags geben dir strikte Kontrolle über deinen Netzwerk-Traffic und deine API-Responses. Halte deine internen Models komplett umfassend, aber nutze deine Dump-Methoden, um sicherzustellen, dass deine externen Payloads genau so schlank bleiben, wie sie sein müssen. Danke fürs Einschalten. Bis zum nächsten Mal!
14

Serialisierungslogik anpassen

3m 32s

Ändere, wie deine Typen bei der Ausgabe dargestellt werden. Du wirst lernen, wie du benutzerdefinierte Field und Model Serializers schreibst, um Daten während der Dumping-Phase zu verändern.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 14 von 20. Was ist, wenn du ein Datum intern als Python-datetime-Objekt speicherst, dein Frontend-API-Contract aber einen rohen Integer-Unix-Timestamp verlangt? Du könntest direkt vor dem Senden über deine Daten loopen, aber das ist unsauber und fehleranfällig. Der sauberere Weg ist, die Serialization-Logik direkt in deinen Pydantic-Models anzupassen. Pydantic gibt dir Decorators, um genau den Moment abzufangen, in dem sich ein Model zurück in ein Dictionary oder JSON verwandelt. Wir fangen mit Field Serializern an. Ein Field Serializer zielt auf ein bestimmtes Attribut ab. Um einen zu erstellen, schreibst du eine ganz normale Methode in deiner Model-Class und setzt den Field-Serializer-Decorator direkt darüber. Du übergibst dem Decorator den Namen des Fields, das du ändern willst. Nehmen wir mal dieses datetime-Szenario. Du hast ein Model mit einem Attribut namens created at, das als Standard-Python-datetime getypt ist. Innerhalb des Models erstellst du eine Methode namens serialize created at. Der Name der Methode ist dabei egal. Darüber platzierst du den Field-Serializer-Decorator, der auf das created at Field zeigt. Die Methode nimmt den datetime-Wert als Input. In der Methode rufst du die Standard-timestamp-Funktion auf diesem datetime auf und gibst den resultierenden Integer zurück. Immer wenn das Model nun seine Daten dumpt, fängt Pydantic das created at Field ab, führt deine Custom-Methode aus und gibt einen sauberen Integer anstelle eines ISO-formatierten Strings aus. Hier ist der entscheidende Punkt. Serializer arbeiten in zwei verschiedenen Modes: plain und wrap. Der plain Mode ist der Default. Wenn ein Serializer im plain Mode ist, verwirft Pydantic seine eigene interne Logik für dieses Field komplett und führt nur deinen Custom-Code aus. Es ist ein kompletter Override. Aber manchmal musst du zuerst die Default-Logik ausführen und dann das Ergebnis modifizieren. Oder vielleicht willst du Errors rund um das Default-Verhalten abfangen. Dann benutzt du den wrap Mode. Um ihn zu aktivieren, übergibst du mode equals wrap an den Decorator. Im wrap Mode erhält deine Methode ein zweites Argument namens Handler. Dieser Handler ist eine Referenz auf Pydantics interne Serialization-Logik. Du kannst den Handler aufrufen, um den Default-Output zu bekommen, ihn zu inspizieren, zu modifizieren oder darauf zurückzufallen, falls deine Custom-Logik fehlschlägt. Das deckt einzelne Fields ab. Wenn du die Struktur des gesamten Outputs ändern musst, benutzt du einen Model Serializer. Das Setup ist fast identisch, aber der Decorator kommt über eine Methode, die auf der gesamten Model-Instanz operiert. Anstatt einen einzelnen Field-Wert zu bekommen, greift die Methode auf die Attribute des Models selbst zu. Wenn du einen Model Serializer in den plain Mode setzt, gibst du eine komplett neue Dictionary-Struktur von Grund auf zurück. Wenn du ihn in den wrap Mode setzt, nimmt deine Methode ein Handler-Argument, genau wie beim Field Serializer. Du rufst den Handler auf, um zuerst das Standard-Model-Dictionary zu bekommen. Dann kannst du neue Top-Level-Keys hinzufügen, private Daten entfernen oder verschachtelte Strukturen flatten, bevor du das finale Dictionary zurückgibst. Der mächtigste Aspekt dieser Decorators ist, dass sie deine internen Python-Typen von deinen externen API-Contracts entkoppeln. So bleibt die Validierung auf dem Weg rein strikt und die Formatierung auf dem Weg raus präzise. Das war's für diese Folge. Danke fürs Zuhören und keep building!
15

JSON Schema aus Models generieren

3m 11s

Verwandle deine Models in selbstdokumentierende API-Verträge. Du wirst lernen, wie du OpenAPI-konforme JSON Schemas generierst und Beispiele direkt in das Schema injizierst.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 15 von 20. Wenn deine API-Schemas in Python bereits strictly typed sind, ist es eine massive Zeitverschwendung, eine separate YAML-Datei für deine OpenAPI-Dokumentation pflegen zu müssen. Am Ende pflegst du zwei Sources of Truth, die unweigerlich auseinanderdriften. Das JSON Schema direkt aus deinen Models zu generieren, löst dieses Synchronisierungsproblem. Jedes Pydantic-Model bringt eine Methode namens model json schema mit. Wenn du diese Methode aufrufst, inspiziert Pydantic dein Model. Es liest die Fields, die Types, die Default-Werte und die Validation Constraints. Anschließend übersetzt es diese ganze interne Python-Logik in ein standardisiertes JSON Schema Dictionary. Genauer gesagt gibt Pydantic den Draft 2020-12 der JSON Schema Spezifikation aus. Das ist der entscheidende Punkt. Da der Output diesem weit verbreiteten Standard entspricht, ist er nativ mit OpenAPI kompatibel. Du definierst deine strengen Validation Rules einmal in Python, und das Framework liefert automatisch die exakte Schema-Definition, die deine externen Consumer brauchen. Es ist keine manuelle Übersetzung nötig. Die Standard-Schema-Generierung verarbeitet Types und grundlegende Constraints perfekt. Aber manchmal musst du Business Logic oder spezifische Formate kommunizieren, die sich nicht allein aus einem Python Type Hint ableiten lassen. Stell dir ein Szenario vor, in dem du ein Configuration-Model für einen neuen Service baust. Das Model enthält ein Field, das ein Dictionary mit Custom Settings akzeptiert. Das Frontend-Team muss genau wissen, wie ein valider Payload aussieht, und nicht nur, dass es ein generisches Objekt ist. Um das zu lösen, nutzt du ein Feature namens json schema extra. Dieser Parameter erlaubt es dir, beliebige Custom Metadata direkt in das generierte JSON Schema einzufügen. Du kannst ihn nutzen, um Mock Examples, Custom Descriptions oder spezifische Keyword Marker hinzuzufügen, die dein API Gateway vielleicht braucht. Du kannst json schema extra auf zwei verschiedenen Ebenen anwenden. Du kannst es an ein einzelnes Field hängen, oder du wendest es auf das gesamte Model an. Um ein Mock Example für dieses spezifische Settings-Field bereitzustellen, definierst du dein Configuration-Model. Dem komplexen Settings-Attribut weist du eine Field-Funktion zu. Innerhalb dieser Field-Funktion übergibst du das Argument json schema extra. Du übergibst ihm ein Dictionary, das den Standard JSON Schema Key namens examples enthält. Der Wert, der auf diesen Key gemappt wird, ist eine Liste, die deinen exakten Mock Configuration Payload enthält. Alternativ, wenn du das gesamte Model statt eines einzelnen Fields dokumentieren willst, definierst du ein model config Dictionary in der Klasse. Innerhalb dieses Configuration Dictionarys übergibst du json schema extra mit einem Schema Level Example. Dieser Ansatz ist extrem nützlich, wenn du zeigen willst, wie mehrere Fields in einem kompletten Request Body zusammenwirken. Wenn du model json schema auf deinem Configuration-Model ausführst, baut Pydantic den Standard Schema Tree. Wenn es deine Fields oder die Model Configuration erreicht, integriert es dein Custom Examples Dictionary direkt in den Standard Output. Das Frontend Tooling liest dieses Schema, parst die examples Property und zeigt den Developern sofort den Mock Payload an. Sie wissen genau, was sie senden müssen, und dein Python-Code bleibt die Single Source of Truth. Die wahre Stärke der Pydantic Schema-Generierung ist, dass jedes externe Tool, das für das JSON Schema Ökosystem gebaut wurde, deine Python Validation Rules ohne Custom Integration sofort konsumieren kann. Danke, dass du ein paar Minuten mit mir verbracht hast. Bis zum nächsten Mal, mach's gut.
16

RootModel: Wenn deine Payload kein Dictionary ist

3m 32s

Behandle nicht standardmäßige JSON-Payloads elegant. Du wirst entdecken, wie RootModel es dir ermöglicht, Arrays und Primitiven auf Root-Ebene zu parsen, während die Fähigkeiten des BaseModel erhalten bleiben.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 16 von 20. Standard Models gehen davon aus, dass dein eingehender JSON Payload ein Object mit Keys und Values ist. Aber was passiert, wenn ein Endpoint ein Top-Level Array direkt oder einfach einen standalone String akzeptieren muss, ohne ihn in ein Dictionary zu wrappen? Genau dafür ist RootModel: Wenn dein Payload kein Dictionary ist, konzipiert. Wenn du ein Standard Base Model verwendest, mappt Pydantic deine Class Attributes auf JSON Keys. Wenn du einem Standard Model eine raw List schickst, wie zum Beispiel ein JSON Array aus Zahlen, schlägt die Validation fehl. Es erwartet eine Dictionary-Struktur. Um das zu umgehen, zwingen Entwickler den Client oft dazu, den Payload zu ändern. Sie erstellen einen Dummy Key, vielleicht namens items, und wrappen das Array in ein Object. Am Ende verbiegst du dein API-Design nur, um deine Validation Library glücklich zu machen. RootModel beseitigt diese Reibung. Es ist ein spezielles Pydantic Model, das genau für Payloads entwickelt wurde, bei denen die äußerste Struktur eine List, ein Tuple oder ein primitiver Typ wie ein Integer oder ein String ist. Stell dir einen Bulk-Delete Endpoint vor. Du möchtest, dass der Client ein raw JSON Array mit Integer User IDs sendet, sonst nichts. Um das zu handhaben, importierst du RootModel aus Pydantic. Du definierst eine neue Class, vielleicht namens UserIdList, und lässt sie von RootModel erben. Du parametrisierst diese Vererbung mit einer List von Integers. Wenn das raw JSON Array auf dem Server ankommt, übergibst du es direkt an die model validate Methode deiner UserIdList Class. Pydantic akzeptiert das Top-Level Array nativ. Es iteriert durch den Payload, stellt sicher, dass jedes einzelne Item ein valider Integer ist, und gibt eine vollständig validierte Model Instance zurück. Hier ist der entscheidende Punkt. Obwohl es eine flache List validiert, bietet ein RootModel exakt dasselbe Interface wie ein reguläres Model. Du hast weiterhin Zugriff auf die Standardmethoden. Du kannst model dump aufrufen, um die Daten zurück in Python Objects zu konvertieren, oder model dump json, um einen raw String zu generieren. Weil es in deinem Payload keine benannten Fields gibt, brauchst du einen Weg, um auf die Daten zuzugreifen, sobald sie validiert sind. Pydantic speichert die geparsten Daten in einem einzigen Attribute, das exakt root heißt. Wenn du über diese validierten User IDs loopen willst, iterierst du einfach über das root Attribute deiner Model Instance. Dieser Mechanismus ist nicht auf Lists beschränkt. Du kannst ein RootModel für einen einzelnen String oder einen Integer definieren. Wenn du einen standalone String Payload erhältst, ihn aber durch strenge Length Checks oder Pattern Matching schicken musst, erlaubt dir die Definition als RootModel vom Typ String, diese Validation Rules nativ anzuhängen. Die Daten bleiben ein einfacher String im Payload, erhalten aber den vollen Schutz der Validation Engine. Wann immer du dich dabei ertappst, einen Dictionary Key zu erfinden, nur damit Pydantic etwas zum Parsen hat, benutzt du das falsche Tool. Verwende RootModel, um deinen Validation Layer an deinen API Contract anzupassen, anstatt deinen API Contract zu ändern, um deinen Validation Layer zufriedenzustellen. Danke fürs Zuhören. Passt auf euch auf!
17

Standard Dataclasses vs. Pydantic Dataclasses

4m 01s

Bringe Validierung in deine nativen Python-Klassen. Du wirst lernen, wann du den Pydantic dataclass-Decorator verwenden solltest, um Legacy-Codebasen nachzurüsten, ohne alles neu schreiben zu müssen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 17 von 20. Du hast eine riesige Codebase, die komplett auf Standard-Python-Dataclasses aufbaut, und dir wird klar, dass du dringend Runtime Validation brauchst. Du denkst vielleicht, du musst alles neu schreiben, um von einem BaseModel zu erben. Musst du aber nicht. Heute schauen wir uns Standard-Dataclasses im Vergleich zu Pydantic-Dataclasses an. Die Python Standard Library bietet einen Dataclass-Decorator, der hervorragend dafür geeignet ist, Boilerplate zu reduzieren. Er schreibt die Initialization-, Representation- und Equality-Methoden für dich. Allerdings vertraut er deinen Inputs blind. Wenn du ein Age-Attribut als Integer deklarierst und ihm einen String übergibst, akzeptiert die Standard-Dataclass den String einfach. Sie liefert zwar Type Hints für die statische Analyse, bietet aber null Runtime Safety. Pydantic löst das mit einem eigenen Dataclass-Decorator. Er ist speziell als Drop-in-Replacement für die Version aus der Standard Library konzipiert. Du behältst genau dieselbe Klassenstruktur bei. Du fügst keine Base Classes hinzu. Du änderst lediglich dein Import-Statement, um den Decorator aus dem pydantic dot dataclasses Modul statt aus der Standard Library zu laden. Stell dir diese Legacy-Codebase vor, die auf Standard-Dataclasses aufbaut. Du findest eine Dataclass, die ein Configuration-Object verwaltet. Du tauschst den Standard-Decorator gegen den Pydantic-Decorator aus. Ab sofort fängt Pydantic die Initialization ab, wann immer deine Application dieses Configuration-Object erstellt. Es liest deine bestehenden Type Hints und erzwingt sie. Wenn ein ungültiger Typ übergeben wird, versucht Pydantic, ihn zu coercen. Wenn die Coercion fehlschlägt, wirft es sofort einen Validation Error. Du erhältst strikte, type-checked Assignments mit null strukturellen Änderungen an deinem Inheritance Tree. Hier ist die entscheidende Erkenntnis: Wenn dir beide Optionen Validation bieten, musst du den Unterschied zwischen einer Pydantic-Dataclass und einem Standard-BaseModel verstehen. Sie behandeln die zugrundeliegenden Daten unterschiedlich. Ein BaseModel ist grundlegend um Dictionary-Parsing herum aufgebaut und bietet eine große Auswahl an Built-in-Methoden für den Datenexport. Eine Pydantic-Dataclass bleibt im Kern eine Standard-Python-Klasse und behält ihren traditionellen Memory Footprint und ihr Verhalten bei. Weil sie eine Standardklasse bleibt, ändert sich die Art und Weise, wie Pydantic die Validation anwendet. Wenn du eine Pydantic-Dataclass instanziierst, werden die Argumente kopiert. Die Daten durchlaufen Pydantics Core Validation Engine, die sie parst und neue Objekte konstruiert, damit sie zu deinen Type Hints passen. Es referenziert nicht einfach nur die ursprünglichen, mutablen Inputs, die du übergeben hast. Wenn du eine Liste an eine Pydantic-Dataclass übergibst, verarbeitet der Validator sie, validiert die internen Elemente und weist der Instanz eine komplett neue Liste zu. Die ursprüngliche Input-Liste und das Attribut in deiner Dataclass sind nicht mehr dasselbe Objekt im Memory. Dieses Copying-Verhalten stellt sicher, dass deine Daten sich strikt an das Schema halten, ohne die ursprünglichen Input-Variablen zu mutieren. Der Hauptnutzen der Pydantic-Dataclass besteht darin, die Lücke zwischen Standard-Python-Paradigmen und strikter Validation zu schließen. Wenn du einen sauberen Migration Path für Legacy-Code brauchst, der bereits Standard-Dataclasses verwendet, tausch einfach den Decorator aus, um sofortige Type Safety zu erhalten und gleichzeitig deine gesamte bestehende Class Semantics beizubehalten. Wenn dir der Podcast gefällt und du die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
18

Feinabstimmung der Model Configuration

3m 44s

Kontrolliere die Striktheit deines gesamten Models. Du wirst lernen, wie du das ConfigDict verwendest, um zusätzliche Attribute zu verbieten, Instanzen einzufrieren und Zuweisungen zu validieren.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 18 von 20. Standardmäßig ignoriert Pydantic alle zusätzlichen JSON Keys, die du ihm sendest. In einer strikten API ist das unbemerkte Schlucken unbekannter Daten ein massives Sicherheitsrisiko. Um das zu beheben, brauchst du Fine-Tuning Model Configuration. Um das Verhalten eines Models global zu ändern, definierst du ein Class Attribute namens model config. Dem weist du ein ConfigDict zu, ein typisiertes Dictionary, das direkt von Pydantic importiert wird. Diese Zuweisung platzierst du direkt in deinem Model neben deinen Field Definitions. Da ConfigDict typisiert ist, erkennt dein Code Editor Tippfehler, wenn du versuchst, eine ungültige Configuration Option zu übergeben. Welche Regeln auch immer du in dieses Dictionary packst, sie bestimmen, wie das gesamte Model Daten parst, validiert und speichert. Bauen wir mal ein striktes Security Settings Model für eine Application. Ein böswilliger Client könnte einen JSON Payload mit unerwarteten Fields senden, vielleicht um ein Admin Flag zu injecten oder einen versteckten Parameter zu überschreiben. Standardmäßig setzt Pydantic das Verhalten für extra Fields auf ignore. Es liest die Fields, die es erwartet, droppt die unbekannten Daten komplett stillschweigend und erstellt das Model. Um diese Lücke zu schließen, fügst du den extra Parameter zu deinem ConfigDict hinzu und setzt seinen Wert auf den String forbid. Wenn ein Client nun einen unerwarteten Key sendet, wirft Pydantic sofort einen Validation Error. Der Request schlägt direkt fehl und weist den fehlerhaften Payload explizit zurück, noch bevor deine Application Logic ihn überhaupt verarbeitet. Damit ist die Grenze zwischen der Außenwelt und deinem System abgedeckt. Aber was passiert innerhalb deines Systems, nachdem das Model erstellt wurde? Pydantic validiert Daten normalerweise nur während der Initialisierung. Wenn ein anderer Entwickler später Code schreibt, der ein Attribute einer bestehenden Model Instance ändert, hält sich Pydantic raus. Du könntest versehentlich einen Raw String einem Integer Field zuweisen, und das Model würde es akzeptieren. Um das zu verhindern, kannst du validate assignment in deinem ConfigDict auf true setzen. Wenn das aktiviert ist, fängt Pydantic jedes Mal, wenn ein Attribute im Memory geändert wird, die Änderung ab und führt exakt dieselbe Validation Logic aus, die es auch bei der Erstellung verwendet. Manchmal ist selbst das Validieren von Mutations für Security Configurations zu durchlässig. Vielleicht willst du eine absolute Garantie, dass die Settings nach dem initialen Check von keinem Teil deines Codes im Memory verändert werden können. Hier wird es interessant. Du kannst den frozen Parameter in deiner Model Configuration auf true setzen. Das macht die gesamte Model Instance immutable. Wenn eine Downstream Function versucht, ein Field zu updaten, wirft Pydantic einen Error. Ein frozen Model verhält sich exakt wie ein Python Tuple. Weil es sich nicht ändern kann, ist es absolut sicher, ein frozen Model über verschiedene Teile deiner Application hinweg zu sharen, und es kann sogar sicher als Key in einem Python Dictionary oder einem In-Memory Cache genutzt werden. Indem du diese Configuration Options in deinem ConfigDict kombinierst, verwandelst du ein Model von einem flexiblen Data Parser in eine absolute, unnachgiebige Grenze. Das war's für diese Folge. Danke fürs Zuhören und keep building!
19

Application Configuration mit Pydantic Settings

3m 43s

Verwalte deine Umgebungsvariablen wie ein Profi. Du wirst lernen, wie das pydantic-settings-Paket das Parsen von Secrets, Dot-Env-Dateien und Präfixen automatisiert.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 19 von 20. Hör auf, Strings aus dem Betriebssystem zu ziehen und die Daumen zu drücken, dass sie sich sauber in einen Integer casten lassen. Wahrscheinlich hast du schon Dutzende von Utility-Files geschrieben, die Standardaufrufe von Umgebungsvariablen wrappen, nur um zu verhindern, dass ein fehlender Konfigurationswert deine Application zur Runtime zum Absturz bringt. Application Configuration mit Pydantic Settings ersetzt diesen ganzen Boilerplate. Während Standard-Pydantic die allgemeine Data Validation übernimmt, erfordert das Verwalten von Umgebungsvariablen die Installation des separaten pydantic-settings Packages. Dieses Package stellt eine spezielle Klasse namens BaseSettings bereit. Anstatt Variablen manuell zu fetchen und eigene Parsing-Logik zu schreiben, deklarierst du eine Klasse, die von BaseSettings erbt. Du definierst deine Konfigurationsfelder genau wie in einem Standard-Pydantic-Model, komplett mit Python Type Hints und Default-Werten. Wenn du diese Klasse instanziierst, liest Pydantic automatisch deine System-Umgebungsvariablen. Es mappt die Variablennamen standardmäßig case-insensitive auf deine Klassenattribute. Wenn du ein Database-Timeout-Feld als Integer definiert hast und die Umgebungsvariable einen String liefert, castet Pydantic diesen String in ein echtes Integer-Objekt. Enthält die Umgebungsvariable beliebigen Text anstelle einer Zahl, wirft Pydantic direkt beim Application Startup einen klaren Validation Error. Dein Programm failt fast, anstatt später während eines aktiven Database Calls unvorhersehbar abzustürzen. In größeren Environments kollidieren globale Variablennamen häufig. Vielleicht hast du mehrere Services, die auf demselben Host laufen und alle nach einer Variable suchen, die einfach database URL heißt. BaseSettings löst das, indem du in der Model Configuration ein Environment Prefix definieren kannst. Wenn du das Prefix auf app underscore setzt, sucht Pydantic nicht mehr nach exakten Field Name Matches. Stattdessen sucht es gezielt nach der Umgebungsvariable app underscore database URL, um ein Feld namens database URL zu befüllen. Dein Python Application Code greift weiterhin einfach als database URL auf die Property zu, wodurch das Operating System Prefix komplett vor deiner Business Logic verborgen bleibt. Hier ist der entscheidende Punkt. Du musst deine Python-Objekte nicht flatten, nur um Umgebungsvariablen zu lesen. Konfigurationen werden oft komplex und erfordern nested Datenstrukturen. Du könntest eine Main Settings Class haben, die ein eigenes Sub-Model für Database Settings und ein weiteres für Logging enthält. Pydantic unterstützt das Resolven dieser nested Strukturen mithilfe einer Double Underscore Convention. Wenn deine Main Settings Class ein Feld namens database hat, das selbst auf ein Model mit einem Timeout-Feld verweist, sucht Pydantic nach einer Umgebungsvariable namens database double underscore timeout. Wenn du ein Prefix verwendest, wird dieses natürlich ebenfalls vorangestellt, was dann zu so etwas wie app underscore database double underscore timeout führt. Dieser Mechanismus erlaubt es dir, strictly typed, hierarchische Configuration Objects in deinem Source Code zu pflegen und sie gleichzeitig sauber auf standardmäßige, flat Umgebungsvariablen zu mappen. Der wahre Wert von BaseSettings liegt nicht nur im Eliminieren von Boilerplate-Code, sondern in der Garantie, dass bei einem erfolgreichen Start deiner Application ihr gesamter Configuration State vollständig vorhanden, explicitly typed und absolut safe to consume ist. Danke fürs Zuhören, Happy Coding zusammen!
20

Unter der Haube: Custom Core Schemas

3m 34s

Dies ist die letzte Episode der Serie! Übernimm die ultimative Kontrolle über die Validierungs-Engine. Du wirst lernen, wie du eine __get_pydantic_core_schema__-Methode schreibst, um dem Rust-Core beizubringen, wie er mit völlig fremden Python-Objekten umgeht.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. Pydantic: Data Validation, Folge 20 von 20. Du bindest eine starre, undokumentierte Library von einem anderen Team ein und musst deren Objekte durch deine strenge Validation Pipeline leiten. Das Objekt hat absolut kein Konzept von Pydantic, und du kannst den Source Code nicht anfassen. Wenn Annotations und einfache Validators nicht ausreichen, musst du direkt mit der Engine sprechen – und das bedeutet, unter die Haube zu schauen und Custom Core Schemas zu schreiben. Normalerweise findet Pydantic heraus, wie es deine Daten validieren soll, indem es Type Hints liest. Wenn du ihm ein fremdes Objekt übergibst, stößt es an seine Grenzen. Um das zu beheben, definierst du eine Methode namens dunder get pydantic core schema. Diese Methode fungiert als direkte Übersetzungsschicht. Sie umgeht die High-Level Python Wrapper und füttert Anweisungen direkt in Pydantic Core, die zugrunde liegende Rust Engine, die die eigentliche Validation Logic übernimmt. Wenn du diese Methode implementierst, erhält sie den Source Type und einen Handler. Der Handler funktioniert genau wie Middleware in einem Web Framework. Du musst nicht das gesamte Validation Schema von Grund auf neu schreiben. Du kannst den Handler bitten, das Default Schema für einen bestimmten Typ zu generieren, und dann deine eigene Custom Logic um diesen Output herum wickeln. Nimm den Legacy Database Connection Wrapper als Beispiel. Angenommen, der einzige Weg, dieses Objekt zu initialisieren, ist die Übergabe eines bestimmten Integers, wie einer Connection ID. Du willst, dass Pydantic einen Integer aus einem API Request akzeptiert, ihn validiert und dir das vollständig instanziierte Connection Object zurückgibt. Weil du die Legacy Class nicht direkt modifizieren kannst, definierst du einen Custom Type mithilfe von Python Annotations. Innerhalb dieser Annotation stellst du deine Custom Core Schema Method bereit. Hier ist die entscheidende Erkenntnis. Anstatt rohe Dictionaries zu schreiben, nutzt du das Core Schema Module von Pydantic, das Helper Functions bietet, um diese Strukturen sicher zu bauen. Zuerst bittest du den Handler, ein Standard Integer Schema zu bauen. Als Nächstes baust du ein Chain Schema. Du weist die Engine an, zuerst die Standard Integer Validation auszuführen. Wenn der Input tatsächlich ein Integer ist, leitet die Engine ihn an eine Custom Python Function weiter, die du bereitstellst. Diese Funktion nimmt die Connection ID, initialisiert den Legacy Database Wrapper und gibt das Objekt zurück. Zum Schluss hängst du ein Instance Check Schema an die Chain an, um sicherzustellen, dass der finale Output genau die Legacy Class ist, die du erwartest. Hier wird es interessant. Du gibst diese verschachtelte Struktur an Pydantic zurück. Unter der Haube nimmt Pydantic diese verschachtelten Dictionary Definitions und kompiliert sie in einen nativen Rust Execution Graph. Du hast die Rust Engine von Python aus programmiert und ihr Schritt für Schritt gesagt, wie sie einen rohen Integer aufnimmt, validiert und bei maximaler Geschwindigkeit sicher ein fremdes Objekt konstruiert. Das ist das absolut niedrigste Level an Integration, das Pydantic bietet, und es gibt dir die totale Kontrolle über den Validation Tree, ohne Performance zu opfern. Da dies unsere letzte Folge ist, empfehle ich dir dringend, in die offizielle Pydantic-Dokumentation einzutauchen und hands-on zu versuchen, ein Custom Core Schema zu bauen. Das ist der beste Weg, um zu festigen, wie die Engine tatsächlich denkt. Du kannst auch DEV STORIES DOT EU besuchen, um Themen vorzuschlagen, die du in zukünftigen Serien behandelt haben möchtest. Das war's für heute. Danke fürs Zuhören – leg los und bau etwas Cooles.