Konkret möchte ich, dass das folgende Beispiel funktioniert:
from typing import List from pydantic import BaseModel from fastapi import FastAPI, UploadFile, File app = FastAPI() class DataConfiguration(BaseModel): textColumnNames: List[str] idColumn: str @app.post("/data") async def data(dataConfiguration: DataConfiguration, csvFile: UploadFile = File(...)): pass # read requested id and text columns from csvFile
Wenn dies nicht der richtige Weg für eine POST-Anfrage ist, teilen Sie mir bitte mit, wie ich die erforderlichen Spalten aus einer hochgeladenen CSV-Datei auswählen kann FastAPI.
Gemäß FastAPI-Dokumentation:
Sie können mehrere Formularparameter in einer Pfadoperation deklarieren, aber Sie können nicht auch Body-Felder deklarieren, die Sie als JSON erwarten. da der Text der Anfrage mit application/x-www-form-urlencoded statt mit application/json codiert wird (wenn das Formular Dateien enthält, wird es als codiert). multipart/form-data).
Dies ist keine Einschränkung von FastAPI, es ist Teil des HTTP-Protokolls.
Beachten Sie, dass Sie zuerst python-multipart installiert haben müssen – falls Sie haben es noch nicht getan, da hochgeladene Dateien als „Formulardaten“ gesendet werden. Zum Beispiel:
pip install python-multipart
Es sollte auch beachtet werden, dass in den folgenden Beispielen die Endpunkte mit normaler Definition definiert sind, Sie können jedoch auch asynchrone Definition verwenden (abhängig von Ihren Anforderungen). Weitere Informationen zu def vs. async def in FastAPI finden Sie in dieser Antwort.
Wenn Sie wissen möchten, wie Sie sowohl Dateien als auch eine Liste von Wörterbüchern/JSON-Daten hochladen können, wenden Sie sich bitte an uns Schauen Sie sich diese Antwort sowie diese Antwort und diese Antwort für Arbeitsbeispiele an (die hauptsächlich auf einigen der folgenden Methoden basieren).
Wie hier beschrieben, kann man mit Datei und Formular gleichzeitig Dateien und Formulardateien definieren. Unten finden Sie ein funktionierendes Beispiel. Falls Sie über eine große Anzahl von Parametern verfügen und diese separat vom Endpunkt definieren möchten, schauen Sie sich bitte diese Antwort an, um zu erfahren, wie Sie entkalkende Formularfelder deklarieren und stattdessen eine Abhängigkeitsklasse oder ein Pydantic-Modell verwenden.
app.py
from fastapi import Form, File, UploadFile, Request, FastAPI from typing import List from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates app = FastAPI() templates = Jinja2Templates(directory="templates") @app.post("/submit") def submit( name: str = Form(...), point: float = Form(...), is_accepted: bool = Form(...), files: List[UploadFile] = File(...), ): return { "JSON Payload": { "name": name, "point": point, "is_accepted": is_accepted, }, "Filenames": [file.filename for file in files], } @app.get("/", response_class=HTMLResponse) def main(request: Request): return templates.TemplateResponse("index.html", {"request": request})
Sie können das obige Beispiel testen, indem Sie auf die Vorlage unten unter zugreifen http://127.0.0.1:8000. Wenn Ihre Vorlage keinen Jinja-Code enthält, können Sie alternativ eine einfache HTMLResponse zurückgeben.
templates/index.html
<!DOCTYPE html> <html> <body> <form method="post" action="http://127.0.0.1:8000/submit" enctype="multipart/form-data"> name : <input type="text" name="name" value="foo"><br> point : <input type="text" name="point" value=0.134><br> is_accepted : <input type="text" name="is_accepted" value=True><br> <label for="files">Choose file(s) to upload</label> <input type="file">
Sie können dieses Beispiel auch testen Verwenden der interaktiven Autodocs der OpenAPI/Swagger-Benutzeroberfläche unter /docs, z. B. http://127.0.0.1:8000/docs oder mit Python-Anfragen, wie unten gezeigt:
test.py
from typing import List from pydantic import BaseModel from fastapi import FastAPI, UploadFile, File app = FastAPI() class DataConfiguration(BaseModel): textColumnNames: List[str] idColumn: str @app.post("/data") async def data(dataConfiguration: DataConfiguration, csvFile: UploadFile = File(...)): pass # read requested id and text columns from csvFile
Man könnte neben Abhängigkeiten auch Pydantic-Modelle verwenden, um den /submit-Endpunkt (im Beispiel unten) darüber zu informieren, dass die parametrisierte Variablenbasis von der Basisklasse abhängt. Bitte beachten Sie, dass diese Methode die Basisdaten als Abfrageparameter (nicht als Körperparameter) erwartet, die dann anhand des Pydantic-Modells (in diesem Fall das Basismodell) validiert und in dieses konvertiert werden. Bitte beachten Sie außerdem, dass niemals vertrauliche Daten über die Abfragezeichenfolge übergeben werden sollten, da dies ein ernstes Sicherheitsrisiko darstellt. Weitere Informationen zu diesem Thema finden Sie in dieser Antwort.
Bei der Rückgabe einer Pydantic-Modellinstanz (in diesem Fall Basis) von einem FastAPI-Endpunkt (z. B. /submit-Endpunkt unten) wird im Hintergrund automatisch mit dem jsonable_encoder in einen JSON-String konvertiert, wie in ausführlich erläutert diese Antwort. Wenn Sie das Modell jedoch innerhalb des Endpunkts selbst in einen JSON-String konvertieren lassen möchten, können Sie model_dump_json() von Pydantic (in Pydantic V2), z. B. base.model_dump_json(), verwenden und direkt eine benutzerdefinierte Antwort zurückgeben. wie in der verlinkten Antwort zuvor erklärt; Dadurch wird die Verwendung von jsonable_encoder vermieden. Andernfalls können Sie, um das Modell selbst in ein Diktat umzuwandeln, model_dump() von Pydantic (in Pydantic V2) verwenden, z. B. base.model_dump(), oder einfach dict(base) (Beachten Sie, dass die Rückgabe eines Diktatobjekts von Als Endpunkt würde FastAPI hinter den Kulissen immer noch den jsonable_encoder verwenden, wie in der oben verlinkten Antwort erläutert. Sie können sich auch diese Antwort für die relevanten Pydantic-Methoden und Dokumentation ansehen.
Neben der Verwendung eines Pydantic-Modells für die Abfrageparameter könnte man Abfrageparameter auch direkt im Endpunkt definieren, wie in dieser Antwort gezeigt , sowie diese Antwort und diese Antwort.
Neben den Basisabfrageparametern erwartet der folgende /submit-Endpunkt auch Dateien, die als Multipart-/Formulardaten in der Anfrage codiert sind body.
app.py
pip install python-multipart
Sie können es erneut mit der folgenden Vorlage testen, die dieses Mal JavaScript verwendet, um das Aktionsattribut von zu ändern das Formularelement, um die Formulardaten stattdessen als Abfrageparameter an die URL zu übergeben Formulardaten.
templates/index.html
from fastapi import Form, File, UploadFile, Request, FastAPI from typing import List from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates app = FastAPI() templates = Jinja2Templates(directory="templates") @app.post("/submit") def submit( name: str = Form(...), point: float = Form(...), is_accepted: bool = Form(...), files: List[UploadFile] = File(...), ): return { "JSON Payload": { "name": name, "point": point, "is_accepted": is_accepted, }, "Filenames": [file.filename for file in files], } @app.get("/", response_class=HTMLResponse) def main(request: Request): return templates.TemplateResponse("index.html", {"request": request})
Das obige ist der detaillierte Inhalt vonWie akzeptiere ich sowohl JSON- als auch Datei-Uploads in einer FastAPI-POST-Anfrage?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!