具體來說,我希望以下範例能夠工作:
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
如果這不是POST 請求的正確方法,請告訴我如何從上傳的CSV 檔案中選擇所需的列FastAPI。
根據FastAPI 文件:
您可以在路徑操作中聲明多個Form 參數,但不能同時聲明您希望以JSON 形式接收的Body 字段,因為請求的正文將使用application/x-www-form-urlencoded 而不是application/json進行編碼(當表單包含檔案時,它會被編碼為multipart/form-data)。
這不是 FastAPI 的限制,它是 HTTP 協定的一部分。
請注意,您需要先安裝 python-multipart — 如果您還沒有這樣做,因為上傳的檔案是作為「表單資料」發送的。例如:
pip install python-multipart
還應該注意的是,在下面的範例中,端點是使用普通 def 定義的,但您也可以使用 async def (根據您的需求)。請查看此答案,以了解有關 FastAPI 中 def 與 async def 的更多詳細資訊。
如果您正在尋找如何上傳檔案和字典/JSON 資料清單,請看看這個答案,以及這個答案和這個工作範例的答案(主要基於以下一些方法)。
如此處所述,可以使用檔案和表單同時定義檔案和表單欄位。下面是一個工作範例。如果您有大量參數並希望與端點分開定義它們,請查看此答案,以了解如何使用依賴項類別或 Pydantic 模型來聲明貼花表單欄位。
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})
您可以透過造訪下面的範本來測試上面的範例http://127.0.0.1:8000。如果您的模板不包含任何 Jinja 程式碼,您也可以傳回一個簡單的 HTMLResponse。
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">
您也可以測試此範例使用 /docs 處的互動式 OpenAPI/Swagger UI 自動文檔,例如http://127.0.0.1:8000/docs,或使用Python請求,如下圖:
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
也可以使用 Pydantic 模型以及依賴項來通知 /submit 端點(在下面的範例中)參數化變數 base 依賴 Base 類別。請注意,此方法需要將基礎資料作為查詢(而不是主體)參數,然後對其進行驗證並轉換為 Pydantic 模型(在本例中,即基礎模型)。另外,請注意,永遠不應該透過查詢字串傳遞敏感數據,因為這會帶來嚴重的安全風險 - 請查看此答案以獲取有關該主題的更多詳細資訊。
返回Pydantic 模型實例時(在本例中,這是基礎)來自FastAPI 端點(例如下面的/submit 端點),它將使用jsonable_encoder 在幕後自動轉換為JSON 字串,如本節中詳細說明的回答。但是,如果您希望在端點內自行將模型轉換為JSON 字串,您可以使用Pydantic 的model_dump_json() (在Pydantic V2 中),例如,base.model_dump_json(),並直接返回自定義響應,正如之前鏈接的答案中所解釋的;因此,避免使用jsonable_encoder。否則,為了自己將模型轉換為字典,您可以使用Pydantic 的model_dump() (在Pydantic V2 中),例如,base.model_dump(),或簡單地dict(base) (請注意,從返回一個dict 物件一個端點,FastAPI 仍然會在幕後使用jsonable_encoder,如上面連結的答案中所述)。您也可以查看此答案以取得相關的 Pydantic 方法和文件。
除了使用 Pydantic 模型作為查詢參數之外,還可以直接在端點中定義查詢參數,如本答案所示,以及這個答案和這個答案。
除了基本查詢參數之外,以下/submit 端點還需要在請求中編碼為multipart/form-data 的檔案body.
app.py
pip install python-multipart
app.py
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})app.pyapp.pyapp.py同樣,您可以使用下面的模板進行測試,這次使用JavaScript 來修改form元素,以便將表單資料作為查詢參數傳遞到 URL 而不是表單資料。 templates/index.html
以上是如何在 FastAPI POST 請求中接受 JSON 和文件上傳?的詳細內容。更多資訊請關注PHP中文網其他相關文章!