在 FastAPI 中,您可以建立可以接受表單或 JSON 正文的端點使用不同的方法。以下是一些選項:
此選項涉及建立一個依賴函數,該函數檢查Content-Type 請求標頭的值並使用Starlette 的方法解析正文
<code class="python">from fastapi import FastAPI, Depends, Request from starlette.datastructures import FormData app = FastAPI() async def get_body(request: Request): content_type = request.headers.get('Content-Type') if content_type is None: raise HTTPException(status_code=400, detail='No Content-Type provided!') elif content_type == 'application/json': return await request.json() elif (content_type == 'application/x-www-form-urlencoded' or content_type.startswith('multipart/form-data')): try: return await request.form() except Exception: raise HTTPException(status_code=400, detail='Invalid Form data') else: raise HTTPException(status_code=400, detail='Content-Type not supported!') @app.post('/') def main(body = Depends(get_body)): if isinstance(body, dict): # if JSON data received return body elif isinstance(body, FormData): # if Form/File data received msg = body.get('msg') items = body.getlist('items') return msg</code>
另一個選項是使用單一端點,並將檔案和/或表單資料參數定義為可選。如果任何參數有值傳遞給它們,則表示請求是 application/x-www-form-urlencoded 或 multipart/form-data。否則,它可能是一個 JSON 請求。
<code class="python">from fastapi import FastAPI, UploadFile, File, Form from typing import Optional, List app = FastAPI() @app.post('/') async def submit(items: Optional[List[str]] = Form(None), files: Optional[List[UploadFile]] = File(None)): # if File(s) and/or form-data were received if items or files: filenames = None if files: filenames = [f.filename for f in files] return {'File(s)/form-data': {'items': items, 'filenames': filenames}} else: # check if JSON data were received data = await request.json() return {'JSON': data}</code>
您也可以使用中間件來檢查傳入請求並將其重新路由到/submitJSON 或/ SubmitForm 端點,具體取決於請求的Content-Type。
<code class="python">from fastapi import FastAPI, Request from fastapi.responses import JSONResponse app = FastAPI() @app.middleware("http") async def some_middleware(request: Request, call_next): if request.url.path == '/': content_type = request.headers.get('Content-Type') if content_type is None: return JSONResponse( content={'detail': 'No Content-Type provided!'}, status_code=400) elif content_type == 'application/json': request.scope['path'] = '/submitJSON' elif (content_type == 'application/x-www-form-urlencoded' or content_type.startswith('multipart/form-data')): request.scope['path'] = '/submitForm' else: return JSONResponse( content={'detail': 'Content-Type not supported!'}, status_code=400) return await call_next(request) @app.post('/') def main(): return @app.post('/submitJSON') def submit_json(item: Item): return item @app.post('/submitForm') def submit_form(msg: str = Form(...), items: List[str] = Form(...), files: Optional[List[UploadFile]] = File(None)): return msg</code>
您可以使用 Python 的 requests 庫測試上述選項:
<code class="python">import requests url = 'http://127.0.0.1:8000/' files = [('files', open('a.txt', 'rb')), ('files', open('b.txt', 'rb'))] payload ={'items': ['foo', 'bar'], 'msg': 'Hello!'} # Send Form data and files r = requests.post(url, data=payload, files=files) print(r.text) # Send Form data only r = requests.post(url, data=payload) print(r.text) # Send JSON data r = requests.post(url, json=payload) print(r.text)</code>
以上是如何在單一 FastAPI 端點中處理表單和 JSON 資料?的詳細內容。更多資訊請關注PHP中文網其他相關文章!