Fortgeschrittene Konfiguration der Pfadoperation¶
OpenAPI operationId¶
Achtung
Wenn Sie kein âExperteâ fĂŒr OpenAPI sind, brauchen Sie dies wahrscheinlich nicht.
Mit dem Parameter operation_id können Sie die OpenAPI operationId festlegen, die in Ihrer Pfadoperation verwendet werden soll.
Sie mĂŒssten sicherstellen, dass sie fĂŒr jede Operation eindeutig ist.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", operation_id="some_specific_id_you_define")
async def read_items():
return [{"item_id": "Foo"}]
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.
from fastapi import FastAPI
from fastapi.routing import APIRoute
app = FastAPI()
@app.get("/items/")
async def read_items():
return [{"item_id": "Foo"}]
def use_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.
"""
for route in app.routes:
if isinstance(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.
Von OpenAPI ausschlieĂen¶
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:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", include_in_schema=False)
async def read_items():
return [{"item_id": "Foo"}]
Fortgeschrittene Beschreibung mittels Docstring¶
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.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_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.
"""
return item
đ€ Other versions and variants
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_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.
"""
return item
from typing import Set, Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
tags: Set[str] = set()
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_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.
"""
return item
ZusĂ€tzliche Responses¶
Sie haben wahrscheinlich gesehen, wie man das response_model und den status_code fĂŒr eine Pfadoperation deklariert.
Das definiert die Metadaten der Haupt-Response einer Pfadoperation.
Sie können auch zusÀtzliche Responses mit deren Modellen, Statuscodes usw. deklarieren.
Es gibt hier in der Dokumentation ein ganzes Kapitel darĂŒber, Sie können es unter ZusĂ€tzliche Responses in OpenAPI lesen.
OpenAPI-Extra¶
Wenn Sie in Ihrer Anwendung eine Pfadoperation deklarieren, generiert FastAPI automatisch die relevanten Metadaten dieser Pfadoperation, die in das OpenAPI-Schema aufgenommen werden sollen.
Technische Details
In der OpenAPI-Spezifikation wird das Operationsobjekt genannt.
Es hat alle Informationen zur Pfadoperation und wird zur Erstellung der automatischen Dokumentation verwendet.
Es enthÀlt tags, parameters, requestBody, responses, usw.
Dieses Pfadoperation-spezifische OpenAPI-Schema wird normalerweise automatisch von FastAPI generiert, Sie können es aber auch erweitern.
Tipp
Dies ist ein Low-Level-Erweiterungspunkt.
Wenn Sie nur zusĂ€tzliche Responses deklarieren mĂŒssen, können Sie dies bequemer mit ZusĂ€tzliche Responses in OpenAPI tun.
Sie können das OpenAPI-Schema fĂŒr eine Pfadoperation erweitern, indem Sie den Parameter openapi_extra verwenden.
OpenAPI-Erweiterungen¶
Dieses openapi_extra kann beispielsweise hilfreich sein, um OpenAPI-Erweiterungen zu deklarieren:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", openapi_extra={"x-aperture-labs-portal": "blue"})
async def read_items():
return [{"item_id": "portal-gun"}]
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:
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"summary": "Read Items",
"operationId": "read_items_items__get",
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {}
}
}
}
},
"x-aperture-labs-portal": "blue"
}
}
}
}
Benutzerdefiniertes OpenAPI-Pfadoperation-Schema¶
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:
from fastapi import FastAPI, Request
app = FastAPI()
def magic_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,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
data = magic_data_reader(raw_body)
return data
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.
Benutzerdefinierter OpenAPI-Content-Type¶
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 im Request 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:
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: list[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.model_validate(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors(include_url=False))
return item
đ€ Other versions and variants
from typing import List
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: List[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.model_validate(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors(include_url=False))
return item
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: list[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.parse_obj(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors())
return item
đ€ Other versions and variants
from typing import List
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: List[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.parse_obj(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors())
return item
Info
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:
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: list[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.model_validate(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors(include_url=False))
return item
đ€ Other versions and variants
from typing import List
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: List[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.model_json_schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.model_validate(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors(include_url=False))
return item
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: list[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.parse_obj(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors())
return item
đ€ Other versions and variants
from typing import List
import yaml
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel, ValidationError
app = FastAPI()
class Item(BaseModel):
name: str
tags: List[str]
@app.post(
"/items/",
openapi_extra={
"requestBody": {
"content": {"application/x-yaml": {"schema": Item.schema()}},
"required": True,
},
},
)
async def create_item(request: Request):
raw_body = await request.body()
try:
data = yaml.safe_load(raw_body)
except yaml.YAMLError:
raise HTTPException(status_code=422, detail="Invalid YAML")
try:
item = Item.parse_obj(data)
except ValidationError as e:
raise HTTPException(status_code=422, detail=e.errors())
return item
Info
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.