Verwendung des Namens der Pfadoperation-Funktion als operationId¶
Wenn Sie die Funktionsnamen Ihrer API als operationIds verwenden möchten, können Sie über alle iterieren und die operation_id jeder Pfadoperation mit deren APIRoute.name überschreiben.
Sie sollten dies tun, nachdem Sie alle Ihre Pfadoperationen hinzugefügt haben.
fromfastapiimportFastAPIfromfastapi.routingimportAPIRouteapp=FastAPI()@app.get("/items/")asyncdefread_items():return[{"item_id":"Foo"}]defuse_route_names_as_operation_ids(app:FastAPI)->None:""" Simplify operation IDs so that generated API clients have simpler function names. Should be called only after all routes have been added. """forrouteinapp.routes:ifisinstance(route,APIRoute):route.operation_id=route.name# in this case, 'read_items'use_route_names_as_operation_ids(app)
Tipp
Wenn Sie app.openapi() manuell aufrufen, sollten Sie vorher die operationIds aktualisiert haben.
Achtung
Wenn Sie dies tun, müssen Sie sicherstellen, dass jede Ihrer Pfadoperation-Funktionen einen eindeutigen Namen hat.
Auch wenn diese sich in unterschiedlichen Modulen (Python-Dateien) befinden.
Um eine Pfadoperation aus dem generierten OpenAPI-Schema (und damit aus den automatischen Dokumentationssystemen) auszuschließen, verwenden Sie den Parameter include_in_schema und setzen Sie ihn auf False:
Sie können die verwendeten Zeilen aus dem Docstring einer Pfadoperation-Funktion einschränken, die für OpenAPI verwendet werden.
Das Hinzufügen eines \f (ein maskiertes „Form Feed“-Zeichen) führt dazu, dass FastAPI die für OpenAPI verwendete Ausgabe an dieser Stelle abschneidet.
Sie wird nicht in der Dokumentation angezeigt, aber andere Tools (z. B. Sphinx) können den Rest verwenden.
fromtypingimportSet,UnionfromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=Nonetags:Set[str]=set()@app.post("/items/",response_model=Item,summary="Create an item")asyncdefcreate_item(item:Item):""" Create an item with all the information: - **name**: each item must have a name - **description**: a long description - **price**: required - **tax**: if the item doesn't have tax, you can omit this - **tags**: a set of unique tag strings for this item \f :param item: User input. """returnitem
Wenn Sie in Ihrer Anwendung eine Pfadoperation deklarieren, generiert FastAPI automatisch die relevanten Metadaten dieser Pfadoperation, die in das OpenAPI-Schema aufgenommen werden sollen.
Wenn Sie die automatische API-Dokumentation öffnen, wird Ihre Erweiterung am Ende der spezifischen Pfadoperation angezeigt.
Und wenn Sie die resultierende OpenAPI sehen (unter /openapi.json in Ihrer API), sehen Sie Ihre Erweiterung auch als Teil der spezifischen Pfadoperation:
Das Dictionary in openapi_extra wird mit dem automatisch generierten OpenAPI-Schema für die Pfadoperation zusammengeführt (mittels Deep Merge).
Sie können dem automatisch generierten Schema also zusätzliche Daten hinzufügen.
Sie könnten sich beispielsweise dafür entscheiden, den Request mit Ihrem eigenen Code zu lesen und zu validieren, ohne die automatischen Funktionen von FastAPI mit Pydantic zu verwenden, aber Sie könnten den Request trotzdem im OpenAPI-Schema definieren wollen.
Das könnte man mit openapi_extra machen:
fromfastapiimportFastAPI,Requestapp=FastAPI()defmagic_data_reader(raw_body:bytes):return{"size":len(raw_body),"content":{"name":"Maaaagic","price":42,"description":"Just kiddin', no magic here. ✨",},}@app.post("/items/",openapi_extra={"requestBody":{"content":{"application/json":{"schema":{"required":["name","price"],"type":"object","properties":{"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},},}}},"required":True,},},)asyncdefcreate_item(request:Request):raw_body=awaitrequest.body()data=magic_data_reader(raw_body)returndata
In diesem Beispiel haben wir kein Pydantic-Modell deklariert. Tatsächlich wird der Requestbody nicht einmal als JSON geparst, sondern direkt als bytes gelesen und die Funktion magic_data_reader () wäre dafür verantwortlich, ihn in irgendeiner Weise zu parsen.
Dennoch können wir das zu erwartende Schema für den Requestbody deklarieren.
Mit demselben Trick könnten Sie ein Pydantic-Modell verwenden, um das JSON-Schema zu definieren, das dann im benutzerdefinierten Abschnitt des OpenAPI-Schemas für die Pfadoperation enthalten ist.
Und Sie könnten dies auch tun, wenn der Datentyp in der Anfrage nicht JSON ist.
In der folgenden Anwendung verwenden wir beispielsweise weder die integrierte Funktionalität von FastAPI zum Extrahieren des JSON-Schemas aus Pydantic-Modellen noch die automatische Validierung für JSON. Tatsächlich deklarieren wir den Request-Content-Type als YAML und nicht als JSON:
In Pydantic Version 1 hieß die Methode zum Abrufen des JSON-Schemas für ein Modell Item.schema(), in Pydantic Version 2 heißt die Methode Item.model_json_schema().
Obwohl wir nicht die standardmäßig integrierte Funktionalität verwenden, verwenden wir dennoch ein Pydantic-Modell, um das JSON-Schema für die Daten, die wir in YAML empfangen möchten, manuell zu generieren.
Dann verwenden wir den Request direkt und extrahieren den Body als bytes. Das bedeutet, dass FastAPI nicht einmal versucht, den Request-Payload als JSON zu parsen.
Und dann parsen wir in unserem Code diesen YAML-Inhalt direkt und verwenden dann wieder dasselbe Pydantic-Modell, um den YAML-Inhalt zu validieren:
In Pydantic Version 1 war die Methode zum Parsen und Validieren eines Objekts Item.parse_obj(), in Pydantic Version 2 heißt die Methode Item.model_validate().
Tipp
Hier verwenden wir dasselbe Pydantic-Modell wieder.
Aber genauso hätten wir es auch auf andere Weise validieren können.