In Pydantic v1 hieß diese Methode .dict(), in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in .model_dump() umbenannt.
Die Beispiele hier verwenden .dict() für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen .model_dump() verwenden, wenn Sie Pydantic v2 verwenden können.
Wenn wir ein dict wie user_dict nehmen, und es einer Funktion (oder Klassenmethode) mittels **user_dict übergeben, wird Python es „entpacken“. Es wird die Schlüssel und Werte von user_dict direkt als Schlüsselwort-Argumente übergeben.
Wenn wir also das user_dict von oben nehmen und schreiben:
Die Hilfsfunktionen fake_password_hasher und fake_save_user demonstrieren nur den möglichen Fluss der Daten und bieten natürlich keine echte Sicherheit.
Reduzierung von Code-Verdoppelung ist eine der Kern-Ideen von FastAPI.
Weil Verdoppelung von Code die Wahrscheinlichkeit von Fehlern, Sicherheitsproblemen, Desynchronisation (Code wird nur an einer Stelle verändert, aber nicht an einer anderen), usw. erhöht.
Unsere Modelle teilen alle eine Menge der Daten und verdoppeln Attribut-Namen und -Typen.
Das können wir besser machen.
Wir deklarieren ein UserBase-Modell, das als Basis für unsere anderen Modelle dient. Dann können wir Unterklassen erstellen, die seine Attribute (Typdeklarationen, Validierungen, usw.) erben.
Die ganze Datenkonvertierung, -validierung, -dokumentation, usw. wird immer noch wie gehabt funktionieren.
Auf diese Weise beschreiben wir nur noch die Unterschiede zwischen den Modellen (mit Klartext-password, mit hashed_password, und ohne Passwort):
Sie können deklarieren, dass eine Response eine Union mehrerer Typen ist, sprich, einer dieser Typen.
Das wird in OpenAPI mit anyOf angezeigt.
Um das zu tun, verwenden Sie Pythons Standard-Typhinweis typing.Union:
Hinweis
Listen Sie, wenn Sie eine Union definieren, denjenigen Typ zuerst, der am spezifischsten ist, gefolgt von den weniger spezifischen Typen. Im Beispiel oben, in Union[PlaneItem, CarItem] also den spezifischeren PlaneItem vor dem weniger spezifischen CarItem.
fromtypingimportUnionfromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classBaseItem(BaseModel):description:strtype:strclassCarItem(BaseItem):type:str="car"classPlaneItem(BaseItem):type:str="plane"size:intitems={"item1":{"description":"All my friends drive a low rider","type":"car"},"item2":{"description":"Music is my aeroplane, it's my aeroplane","type":"plane","size":5,},}@app.get("/items/{item_id}",response_model=Union[PlaneItem,CarItem])asyncdefread_item(item_id:str):returnitems[item_id]
🤓 Other versions and variants
fromtypingimportUnionfromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classBaseItem(BaseModel):description:strtype:strclassCarItem(BaseItem):type:str="car"classPlaneItem(BaseItem):type:str="plane"size:intitems={"item1":{"description":"All my friends drive a low rider","type":"car"},"item2":{"description":"Music is my aeroplane, it's my aeroplane","type":"plane","size":5,},}@app.get("/items/{item_id}",response_model=Union[PlaneItem,CarItem])asyncdefread_item(item_id:str):returnitems[item_id]
In diesem Beispiel übergeben wir dem Argument response_model den Wert Union[PlaneItem, CarItem].
Da wir es als Wert einem Argument überreichen, statt es als Typannotation zu verwenden, müssen wir Union verwenden, selbst in Python 3.10.
Wenn es eine Typannotation gewesen wäre, hätten wir auch den vertikalen Trennstrich verwenden können, wie in:
some_variable:PlaneItem|CarItem
Aber wenn wir das in der Zuweisung response_model=PlaneItem | CarItem machen, erhalten wir eine Fehlermeldung, da Python versucht, eine ungültige Operation zwischen PlaneItem und CarItem durchzuführen, statt es als Typannotation zu interpretieren.
Genauso können Sie eine Response deklarieren, die eine Liste von Objekten ist.
Verwenden Sie dafür Pythons Standard typing.List (oder nur list in Python 3.9 und darüber):
fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:stritems=[{"name":"Foo","description":"There comes my hero"},{"name":"Red","description":"It's my aeroplane"},]@app.get("/items/",response_model=list[Item])asyncdefread_items():returnitems
🤓 Other versions and variants
fromtypingimportListfromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:stritems=[{"name":"Foo","description":"There comes my hero"},{"name":"Red","description":"It's my aeroplane"},]@app.get("/items/",response_model=List[Item])asyncdefread_items():returnitems
Sie könne auch eine Response deklarieren, die ein beliebiges dict zurückgibt, bei dem nur die Typen der Schlüssel und der Werte bekannt sind, ohne ein Pydantic-Modell zu verwenden.
Das ist nützlich, wenn Sie die gültigen Feld-/Attribut-Namen von vorneherein nicht wissen (was für ein Pydantic-Modell notwendig ist).
In diesem Fall können Sie typing.Dict verwenden (oder nur dict in Python 3.9 und darüber):
Verwenden Sie gerne mehrere Pydantic-Modelle und vererben Sie je nach Bedarf.
Sie brauchen kein einzelnes Datenmodell pro Einheit, wenn diese Einheit verschiedene Zustände annehmen kann. So wie unsere Benutzer-„Einheit“, welche einen Zustand mit password, einen mit password_hash und einen ohne Passwort hatte.