Rumah >pembangunan bahagian belakang >Tutorial Python >Bagaimana untuk menerima kedua-dua JSON dan muat naik fail dalam permintaan FastAPI POST?
Secara khusus, saya mahu contoh di bawah berfungsi:
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
Jika ini bukan cara yang betul untuk permintaan POST, sila beritahu saya cara memilih lajur yang diperlukan daripada fail CSV yang dimuat naik dalam FastAPI.
Mengikut dokumentasi FastAPI:
Anda boleh mengisytiharkan berbilang parameter Borang dalam operasi laluan, tetapi anda juga tidak boleh mengisytiharkan medan Badan yang anda jangkakan akan terima sebagai JSON, kerana permintaan akan mempunyai badan yang dikodkan menggunakan application/x-www-form-urlencoded dan bukannya application/json (apabila borang termasuk fail, ia dikodkan sebagai multipart/form-data).
Ini bukan pengehadan FastAPI, ia adalah sebahagian daripada protokol HTTP.
Perhatikan bahawa anda perlu memasang python-multipart terlebih dahulu—jika anda belum melakukannya—memandangkan fail yang dimuat naik dihantar sebagai "data borang". Contohnya:
pip install python-multipart
Perlu diingatkan juga bahawa dalam contoh di bawah, titik akhir ditakrifkan dengan def biasa, tetapi anda juga boleh menggunakan async def (bergantung pada keperluan anda). Sila lihat jawapan ini untuk mendapatkan butiran lanjut tentang def vs async def dalam FastAPI.
Jika anda sedang mencari cara untuk memuat naik kedua-dua fail dan senarai kamus/data JSON, sila lihat jawapan ini, serta jawapan ini dan jawapan ini untuk contoh kerja (yang kebanyakannya berdasarkan beberapa perkara berikut kaedah).
Seperti yang diterangkan di sini, seseorang boleh mentakrifkan fail dan borang fail pada masa yang sama menggunakan Fail dan Borang. Di bawah adalah contoh kerja. Sekiranya anda mempunyai sejumlah besar parameter dan ingin mentakrifkannya secara berasingan daripada titik akhir, sila lihat jawapan ini tentang cara mengisytiharkan medan Borang decalring, menggunakan kelas pergantungan atau model Pydantic sebaliknya.
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})
Anda boleh menguji contoh di atas dengan mengakses templat di bawah di http://127.0.0.1:8000. Jika templat anda tidak menyertakan sebarang kod Jinja, anda juga boleh mengembalikan HTMLResponse yang mudah.
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">
Anda juga boleh menguji contoh ini menggunakan autodoks OpenAPI/Swagger UI interaktif di /docs, cth., http://127.0.0.1:8000/docs, atau menggunakan permintaan Python, seperti yang ditunjukkan di bawah:
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
Seseorang juga boleh menggunakan model Pydantic, bersama-sama dengan Dependencies, untuk memaklumkan titik akhir /submit (dalam contoh di bawah) bahawa asas pembolehubah parameter bergantung pada kelas Base. Sila ambil perhatian bahawa kaedah ini menjangkakan data asas sebagai parameter pertanyaan (bukan badan), yang kemudiannya disahkan terhadap dan ditukar kepada model Pydantic (dalam kes ini, iaitu model Base). Selain itu, sila ambil perhatian bahawa seseorang itu tidak boleh menghantar data sensitif melalui rentetan pertanyaan, kerana ini menimbulkan risiko keselamatan yang serius—sila lihat jawapan ini untuk mendapatkan butiran lanjut tentang topik itu.
Apabila mengembalikan contoh model Pydantic (dalam kes ini, itu adalah asas) dari titik akhir FastAPI (cth., /serahkan titik akhir di bawah), ia secara automatik akan ditukar menjadi rentetan JSON, di belakang tabir, menggunakan jsonable_encoder, seperti yang dijelaskan secara terperinci dalam jawapan ini. Walau bagaimanapun, jika anda ingin model itu ditukar kepada rentetan JSON sendiri dalam titik akhir, anda boleh menggunakan model_dump_json() Pydantic (dalam Pydantic V2), cth., base.model_dump_json(), dan kembalikan Respons tersuai secara langsung, seperti yang dijelaskan dalam jawapan yang dipautkan tadi; oleh itu, mengelakkan penggunaan jsonable_encoder. Jika tidak, untuk menukar model kepada dict anda sendiri, anda boleh menggunakan model_dump() Pydantic (dalam Pydantic V2), cth., base.model_dump(), atau hanya dict(base) (Perhatikan bahawa mengembalikan objek dict daripada titik akhir, FastAPI masih akan menggunakan jsonable_encoder, di belakang tabir, seperti yang dijelaskan dalam jawapan yang dipautkan di atas). Anda juga boleh melihat jawapan ini untuk kaedah dan dokumentasi Pydantic yang berkaitan.
Selain daripada menggunakan model Pydantic untuk parameter pertanyaan, seseorang juga boleh mentakrifkan parameter pertanyaan secara langsung di titik akhir, seperti yang ditunjukkan dalam jawapan ini , serta jawapan ini dan jawapan ini.
Selain parameter pertanyaan asas, titik akhir /submit berikut juga menjangkakan Fail dikodkan sebagai data berbilang bahagian/borang dalam badan permintaan.
app.py
pip install python-multipart
Sekali lagi, anda boleh mengujinya menggunakan templat di bawah, yang kali ini, menggunakan JavaScript untuk mengubah suai atribut tindakan elemen borang, untuk menghantar data borang sebagai parameter pertanyaan kepada URL dan bukannya form-data.
templat/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})
Atas ialah kandungan terperinci Bagaimana untuk menerima kedua-dua JSON dan muat naik fail dalam permintaan FastAPI POST?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!