Wenn Sie jedoch direkt eine Response zurückgeben, werden die Daten nicht automatisch konvertiert und die Dokumentation wird nicht automatisch generiert (zum Beispiel wird der spezifische „Medientyp“, der im HTTP-Header Content-Type angegeben ist, nicht Teil der generierten OpenAPI).
Sie können aber auch die Response, die Sie verwenden möchten, im Pfadoperation-Dekorator deklarieren.
Der Inhalt, den Sie von Ihrer Pfadoperation-Funktion zurückgeben, wird in diese Response eingefügt.
Und wenn diese Response einen JSON-Medientyp (application/json) hat, wie es bei JSONResponse und UJSONResponse der Fall ist, werden die von Ihnen zurückgegebenen Daten automatisch mit jedem Pydantic response_model konvertiert (und gefiltert), das Sie im Pfadoperation-Dekorator deklariert haben.
Hinweis
Wenn Sie eine Response-Klasse ohne Medientyp verwenden, erwartet FastAPI, dass Ihre Response keinen Inhalt hat, und dokumentiert daher das Format der Response nicht in deren generierter OpenAPI-Dokumentation.
Um beispielsweise noch etwas Leistung herauszuholen, können Sie orjson installieren und verwenden, und die Response als ORJSONResponse deklarieren.
Importieren Sie die Response-Klasse (-Unterklasse), die Sie verwenden möchten, und deklarieren Sie sie im Pfadoperation-Dekorator.
Bei umfangreichen Responses ist die direkte Rückgabe einer Response viel schneller als ein Dictionary zurückzugeben.
Das liegt daran, dass FastAPI standardmäßig jedes enthaltene Element überprüft und sicherstellt, dass es als JSON serialisierbar ist, und zwar unter Verwendung desselben JSON-kompatiblen Encoders, der im Tutorial erläutert wurde. Dadurch können Sie beliebige Objekte zurückgeben, zum Beispiel Datenbankmodelle.
Wenn Sie jedoch sicher sind, dass der von Ihnen zurückgegebene Inhalt mit JSON serialisierbar ist, können Sie ihn direkt an die Response-Klasse übergeben und die zusätzliche Arbeit vermeiden, die FastAPI hätte, indem es Ihren zurückgegebenen Inhalt durch den jsonable_encoder leitet, bevor es ihn an die Response-Klasse übergibt.
Wie in Eine Response direkt zurückgeben gezeigt, können Sie die Response auch direkt in Ihrer Pfadoperation überschreiben, indem Sie diese zurückgeben.
Das gleiche Beispiel von oben, das eine HTMLResponse zurückgibt, könnte so aussehen:
fromfastapiimportFastAPIfromfastapi.responsesimportHTMLResponseapp=FastAPI()@app.get("/items/")asyncdefread_items():html_content=""" <html> <head> <title>Some HTML in here</title> </head> <body> <h1>Look ma! HTML!</h1> </body> </html> """returnHTMLResponse(content=html_content,status_code=200)
Achtung
Eine Response, die direkt von Ihrer Pfadoperation-Funktion zurückgegeben wird, wird in OpenAPI nicht dokumentiert (zum Beispiel wird der Content-Type nicht dokumentiert) und ist in der automatischen interaktiven Dokumentation nicht sichtbar.
Info
Natürlich stammen der eigentliche Content-Type-Header, der Statuscode, usw., aus dem Response-Objekt, das Sie zurückgegeben haben.
In OpenAPI dokumentieren und Response überschreiben¶
Wenn Sie die Response innerhalb der Funktion überschreiben und gleichzeitig den „Medientyp“ in OpenAPI dokumentieren möchten, können Sie den response_class-Parameter verwenden UND ein Response-Objekt zurückgeben.
Die response_class wird dann nur zur Dokumentation der OpenAPI-Pfadoperation* verwendet, Ihre Response wird jedoch unverändert verwendet.
fromfastapiimportFastAPIfromfastapi.responsesimportHTMLResponseapp=FastAPI()defgenerate_html_response():html_content=""" <html> <head> <title>Some HTML in here</title> </head> <body> <h1>Look ma! HTML!</h1> </body> </html> """returnHTMLResponse(content=html_content,status_code=200)@app.get("/items/",response_class=HTMLResponse)asyncdefread_items():returngenerate_html_response()
In diesem Beispiel generiert die Funktion generate_html_response() bereits eine Response und gibt sie zurück, anstatt das HTML in einem str zurückzugeben.
Indem Sie das Ergebnis des Aufrufs von generate_html_response() zurückgeben, geben Sie bereits eine Response zurück, die das Standardverhalten von FastAPI überschreibt.
Aber da Sie die HTMLResponse auch in der response_class übergeben haben, weiß FastAPI, dass sie in OpenAPI und der interaktiven Dokumentation als HTML mit text/html zu dokumentieren ist:
Bedenken Sie, dass Sie Response verwenden können, um alles andere zurückzugeben, oder sogar eine benutzerdefinierte Unterklasse zu erstellen.
Technische Details
Sie können auch from starlette.responses import HTMLResponse verwenden.
FastAPI bietet dieselben starlette.responses auch via fastapi.responses an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
Die Hauptklasse Response, alle anderen Responses erben von ihr.
Sie können sie direkt zurückgeben.
Sie akzeptiert die folgenden Parameter:
content – Ein str oder bytes.
status_code – Ein int-HTTP-Statuscode.
headers – Ein dict von Strings.
media_type – Ein str, der den Medientyp angibt. Z. B. "text/html".
FastAPI (eigentlich Starlette) fügt automatisch einen Content-Length-Header ein. Außerdem wird es einen Content-Type-Header einfügen, der auf dem media_type basiert, und für Texttypen einen Zeichensatz (charset) anfügen.
fromfastapiimportFastAPI,Responseapp=FastAPI()@app.get("/legacy/")defget_legacy_data():data="""<?xml version="1.0"?> <shampoo> <Header> Apply shampoo here. </Header> <Body> You'll have to use soap here. </Body> </shampoo> """returnResponse(content=data,media_type="application/xml")
Nimmt einen asynchronen Generator oder einen normalen Generator/Iterator und streamt den Responsebody.
fromfastapiimportFastAPIfromfastapi.responsesimportStreamingResponseapp=FastAPI()asyncdeffake_video_streamer():foriinrange(10):yieldb"some fake video bytes"@app.get("/")asyncdefmain():returnStreamingResponse(fake_video_streamer())
Verwendung von StreamingResponse mit dateiähnlichen Objekten¶
Wenn Sie ein dateiähnliches (file-like) Objekt haben (z. B. das von open() zurückgegebene Objekt), können Sie eine Generatorfunktion erstellen, um über dieses dateiähnliche Objekt zu iterieren.
Auf diese Weise müssen Sie nicht alles zuerst in den Arbeitsspeicher lesen und können diese Generatorfunktion an StreamingResponse übergeben und zurückgeben.
Das umfasst viele Bibliotheken zur Interaktion mit Cloud-Speicher, Videoverarbeitung und anderen.
Beachten Sie, dass wir, da wir Standard-open() verwenden, welches async und await nicht unterstützt, hier die Pfadoperation mit normalen def deklarieren.
Sie können Ihre eigene benutzerdefinierte Response-Klasse erstellen, die von Response erbt und diese verwendet.
Nehmen wir zum Beispiel an, dass Sie orjson verwenden möchten, aber mit einigen benutzerdefinierten Einstellungen, die in der enthaltenen ORJSONResponse-Klasse nicht verwendet werden.
Sie möchten etwa, dass Ihre Response eingerücktes und formatiertes JSON zurückgibt. Dafür möchten Sie die orjson-Option orjson.OPT_INDENT_2 verwenden.
Sie könnten eine CustomORJSONResponse erstellen. Das Wichtigste, was Sie tun müssen, ist, eine Response.render(content)-Methode zu erstellen, die den Inhalt als bytes zurückgibt:
fromtypingimportAnyimportorjsonfromfastapiimportFastAPI,Responseapp=FastAPI()classCustomORJSONResponse(Response):media_type="application/json"defrender(self,content:Any)->bytes:assertorjsonisnotNone,"orjson must be installed"returnorjson.dumps(content,option=orjson.OPT_INDENT_2)@app.get("/",response_class=CustomORJSONResponse)asyncdefmain():return{"message":"Hello World"}
Statt:
{"message":"Hello World"}
... wird die Response jetzt Folgendes zurückgeben:
{"message":"Hello World"}
Natürlich werden Sie wahrscheinlich viel bessere Möglichkeiten finden, Vorteil daraus zu ziehen, als JSON zu formatieren. 😉