Sie können Beispiele für die Daten deklarieren, die Ihre Anwendung empfangen kann.
Hier sind mehrere Möglichkeiten, das zu tun.
Zusätzliche JSON-Schemadaten in Pydantic-Modellen¶
Sie können examples („Beispiele“) für ein Pydantic-Modell deklarieren, welche dem generierten JSON-Schema hinzugefügt werden.
fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonemodel_config={"json_schema_extra":{"examples":[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}]}}@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults
fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=NoneclassConfig:schema_extra={"examples":[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}]}@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults
fromtypingimportUnionfromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=Nonemodel_config={"json_schema_extra":{"examples":[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}]}}@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults
fromtypingimportUnionfromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=NoneclassConfig:schema_extra={"examples":[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}]}@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults
Diese zusätzlichen Informationen werden unverändert zum für dieses Modell ausgegebenen JSON-Schema hinzugefügt und in der API-Dokumentation verwendet.
In Pydantic Version 2 würden Sie das Attribut model_config verwenden, das ein dict akzeptiert, wie beschrieben in Pydantic-Dokumentation: Configuration.
Sie können json_schema_extra setzen, mit einem dict, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich examples.
Sie können schema_extra setzen, mit einem dict, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich examples.
Tipp
Mit derselben Technik können Sie das JSON-Schema erweitern und Ihre eigenen benutzerdefinierten Zusatzinformationen hinzufügen.
Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benutzeroberfläche usw. hinzuzufügen.
Info
OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für examples hinzugefügt, was Teil des JSON Schema Standards ist.
Zuvor unterstützte es nur das Schlüsselwort example mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch deprecated und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von example nach examples zu migrieren. 🤓
Wenn Sie Field() mit Pydantic-Modellen verwenden, können Sie ebenfalls zusätzliche examples deklarieren:
fromfastapiimportFastAPIfrompydanticimportBaseModel,Fieldapp=FastAPI()classItem(BaseModel):name:str=Field(examples=["Foo"])description:str|None=Field(default=None,examples=["A very nice Item"])price:float=Field(examples=[35.4])tax:float|None=Field(default=None,examples=[3.2])@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults
fromtypingimportUnionfromfastapiimportFastAPIfrompydanticimportBaseModel,Fieldapp=FastAPI()classItem(BaseModel):name:str=Field(examples=["Foo"])description:Union[str,None]=Field(default=None,examples=["A very nice Item"])price:float=Field(examples=[35.4])tax:Union[float,None]=Field(default=None,examples=[3.2])@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults
können Sie auch eine Gruppe von examples mit zusätzlichen Informationen deklarieren, die zu ihren JSON-Schemas innerhalb von OpenAPI hinzugefügt werden.
Hier übergeben wir examples, welches ein einzelnes Beispiel für die in Body() erwarteten Daten enthält:
fromtypingimportAnnotatedfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}],),],):results={"item_id":item_id,"item":item}returnresults
fromtypingimportAnnotated,UnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}],),],):results={"item_id":item_id,"item":item}returnresults
fromtypingimportUnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelfromtyping_extensionsimportAnnotatedapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}],),],):results={"item_id":item_id,"item":item}returnresults
Tipp
Bevorzugen Sie die Annotated-Version, falls möglich.
fromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item=Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}],),):results={"item_id":item_id,"item":item}returnresults
Tipp
Bevorzugen Sie die Annotated-Version, falls möglich.
fromtypingimportUnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item=Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}],),):results={"item_id":item_id,"item":item}returnresults
Beispiel in der Dokumentations-Benutzeroberfläche¶
Mit jeder der oben genannten Methoden würde es in /docs so aussehen:
Sie können natürlich auch mehrere examples übergeben:
fromtypingimportAnnotatedfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},{"name":"Bar","price":"35.4",},{"name":"Baz","price":"thirty five point four",},],),],):results={"item_id":item_id,"item":item}returnresults
fromtypingimportAnnotated,UnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},{"name":"Bar","price":"35.4",},{"name":"Baz","price":"thirty five point four",},],),],):results={"item_id":item_id,"item":item}returnresults
fromtypingimportUnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelfromtyping_extensionsimportAnnotatedapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},{"name":"Bar","price":"35.4",},{"name":"Baz","price":"thirty five point four",},],),],):results={"item_id":item_id,"item":item}returnresults
Tipp
Bevorzugen Sie die Annotated-Version, falls möglich.
fromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Item=Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},{"name":"Bar","price":"35.4",},{"name":"Baz","price":"thirty five point four",},],),):results={"item_id":item_id,"item":item}returnresults
Tipp
Bevorzugen Sie die Annotated-Version, falls möglich.
fromtypingimportUnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Item=Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},{"name":"Bar","price":"35.4",},{"name":"Baz","price":"thirty five point four",},],),):results={"item_id":item_id,"item":item}returnresults
Wenn Sie das tun, werden die Beispiele Teil des internen JSON-Schemas für diese Body-Daten.
Während dies geschrieben wird, unterstützt Swagger UI, das für die Anzeige der Dokumentations-Benutzeroberfläche zuständige Tool, jedoch nicht die Anzeige mehrerer Beispiele für die Daten in JSON Schema. Aber lesen Sie unten für einen Workaround weiter.
Schon bevor JSON Schemaexamples unterstützte, unterstützte OpenAPI ein anderes Feld, das auch examples genannt wurde.
Diese OpenAPI-spezifischenexamples finden sich in einem anderen Abschnitt der OpenAPI-Spezifikation. Sie sind Details für jede Pfadoperation, nicht für jedes JSON-Schema.
Und Swagger UI unterstützt dieses spezielle Feld examples schon seit einiger Zeit. Sie können es also verwenden, um verschiedene Beispiele in der Benutzeroberfläche der Dokumentation anzuzeigen.
Das Format dieses OpenAPI-spezifischen Felds examples ist ein dict mit mehreren Beispielen (anstelle einer liste), jedes mit zusätzlichen Informationen, die auch zu OpenAPI hinzugefügt werden.
Dies erfolgt nicht innerhalb jedes in OpenAPI enthaltenen JSON-Schemas, sondern außerhalb, in der Pfadoperation.
Sie können die OpenAPI-spezifischen examples in FastAPI mit dem Parameter openapi_examples deklarieren, für:
Path()
Query()
Header()
Cookie()
Body()
Form()
File()
Die Schlüssel des dict identifizieren jedes Beispiel, und jeder Wert ("value") ist ein weiteres dict.
Jedes spezifische Beispiel-dict in den examples kann Folgendes enthalten:
summary: Kurze Beschreibung für das Beispiel.
description: Eine lange Beschreibung, die Markdown-Text enthalten kann.
value: Dies ist das tatsächlich angezeigte Beispiel, z. B. ein dict.
externalValue: Alternative zu value, eine URL, die auf das Beispiel verweist. Allerdings wird dies möglicherweise nicht von so vielen Tools unterstützt wie value.
Sie können es so verwenden:
fromtypingimportAnnotatedfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(openapi_examples={"normal":{"summary":"A normal example","description":"A **normal** item works correctly.","value":{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},},"converted":{"summary":"An example with converted data","description":"FastAPI can convert price `strings` to actual `numbers` automatically","value":{"name":"Bar","price":"35.4",},},"invalid":{"summary":"Invalid data is rejected with an error","value":{"name":"Baz","price":"thirty five point four",},},},),],):results={"item_id":item_id,"item":item}returnresults
fromtypingimportAnnotated,UnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(openapi_examples={"normal":{"summary":"A normal example","description":"A **normal** item works correctly.","value":{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},},"converted":{"summary":"An example with converted data","description":"FastAPI can convert price `strings` to actual `numbers` automatically","value":{"name":"Bar","price":"35.4",},},"invalid":{"summary":"Invalid data is rejected with an error","value":{"name":"Baz","price":"thirty five point four",},},},),],):results={"item_id":item_id,"item":item}returnresults
fromtypingimportUnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelfromtyping_extensionsimportAnnotatedapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(openapi_examples={"normal":{"summary":"A normal example","description":"A **normal** item works correctly.","value":{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},},"converted":{"summary":"An example with converted data","description":"FastAPI can convert price `strings` to actual `numbers` automatically","value":{"name":"Bar","price":"35.4",},},"invalid":{"summary":"Invalid data is rejected with an error","value":{"name":"Baz","price":"thirty five point four",},},},),],):results={"item_id":item_id,"item":item}returnresults
Tipp
Bevorzugen Sie die Annotated-Version, falls möglich.
fromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Item=Body(openapi_examples={"normal":{"summary":"A normal example","description":"A **normal** item works correctly.","value":{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},},"converted":{"summary":"An example with converted data","description":"FastAPI can convert price `strings` to actual `numbers` automatically","value":{"name":"Bar","price":"35.4",},},"invalid":{"summary":"Invalid data is rejected with an error","value":{"name":"Baz","price":"thirty five point four",},},},),):results={"item_id":item_id,"item":item}returnresults
Tipp
Bevorzugen Sie die Annotated-Version, falls möglich.
fromtypingimportUnionfromfastapiimportBody,FastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Item=Body(openapi_examples={"normal":{"summary":"A normal example","description":"A **normal** item works correctly.","value":{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},},"converted":{"summary":"An example with converted data","description":"FastAPI can convert price `strings` to actual `numbers` automatically","value":{"name":"Bar","price":"35.4",},},"invalid":{"summary":"Invalid data is rejected with an error","value":{"name":"Baz","price":"thirty five point four",},},},),):results={"item_id":item_id,"item":item}returnresults
OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche¶
Wenn openapi_examples zu Body() hinzugefügt wird, würde /docs so aussehen:
Wenn Sie bereits FastAPI Version 0.99.0 oder höher verwenden, können Sie diese Details wahrscheinlich überspringen.
Sie sind für ältere Versionen relevanter, bevor OpenAPI 3.1.0 verfügbar war.
Sie können dies als eine kurze Geschichtsstunde zu OpenAPI und JSON Schema betrachten. 🤓
Achtung
Dies sind sehr technische Details zu den Standards JSON Schema und OpenAPI.
Wenn die oben genannten Ideen bereits für Sie funktionieren, reicht das möglicherweise aus und Sie benötigen diese Details wahrscheinlich nicht, überspringen Sie sie gerne.
Vor OpenAPI 3.1.0 verwendete OpenAPI eine ältere und modifizierte Version von JSON Schema.
JSON Schema hatte keine examples, daher fügte OpenAPI seiner eigenen modifizierten Version ein eigenes example-Feld hinzu.
OpenAPI fügte auch die Felder example und examples zu anderen Teilen der Spezifikation hinzu:
Aber dann fügte JSON Schema ein examples-Feld zu einer neuen Version der Spezifikation hinzu.
Und dann basierte das neue OpenAPI 3.1.0 auf der neuesten Version (JSON Schema 2020-12), die dieses neue Feld examples enthielt.
Und jetzt hat dieses neue examples-Feld Vorrang vor dem alten (und benutzerdefinierten) example-Feld, im Singular, das jetzt deprecated ist.
Dieses neue examples-Feld in JSON Schema ist nur eine liste von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben).
Info
Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉).
Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Versionen von OpenAPI vor 3.1.0.
Wenn Sie examples innerhalb eines Pydantic-Modells hinzufügen, indem Sie schema_extra oder Field(examples=["something"]) verwenden, wird dieses Beispiel dem JSON-Schema für dieses Pydantic-Modell hinzugefügt.
Und dieses JSON-Schema des Pydantic-Modells ist in der OpenAPI Ihrer API enthalten und wird dann in der Benutzeroberfläche der Dokumentation verwendet.
In Versionen von FastAPI vor 0.99.0 (0.99.0 und höher verwenden das neuere OpenAPI 3.1.0), wenn Sie example oder examples mit einem der anderen Werkzeuge (Query(), Body(), usw.) verwendet haben, wurden diese Beispiele nicht zum JSON-Schema hinzugefügt, das diese Daten beschreibt (nicht einmal zur OpenAPI-eigenen Version von JSON Schema), sondern direkt zur Pfadoperation-Deklaration in OpenAPI (außerhalb der Teile von OpenAPI, die JSON Schema verwenden).
Aber jetzt, da FastAPI 0.99.0 und höher, OpenAPI 3.1.0 verwendet, das JSON Schema 2020-12 verwendet, und Swagger UI 5.0.0 und höher, ist alles konsistenter und die Beispiele sind in JSON Schema enthalten.
Swagger-Benutzeroberfläche und OpenAPI-spezifische examples.¶
Da die Swagger-Benutzeroberfläche derzeit nicht mehrere JSON Schema Beispiele unterstützt (Stand: 26.08.2023), hatten Benutzer keine Möglichkeit, mehrere Beispiele in der Dokumentation anzuzeigen.
Um dieses Problem zu lösen, hat FastAPI 0.103.0Unterstützung für die Deklaration desselben alten OpenAPI-spezifischenexamples-Felds mit dem neuen Parameter openapi_examples hinzugefügt. 🤓
Ich habe immer gesagt, dass ich Geschichte nicht so sehr mag ... und jetzt schauen Sie mich an, wie ich „Technikgeschichte“-Unterricht gebe. 😅
Kurz gesagt: Upgraden Sie auf FastAPI 0.99.0 oder höher, und die Dinge sind viel einfacher, konsistenter und intuitiver, und Sie müssen nicht alle diese historischen Details kennen. 😎