Maison > développement back-end > Tutoriel Python > Comment gérer à la fois les données de formulaire et les données JSON dans un seul point de terminaison FastAPI ?

Comment gérer à la fois les données de formulaire et les données JSON dans un seul point de terminaison FastAPI ?

Patricia Arquette
Libérer: 2024-10-26 23:22:30
original
810 Les gens l'ont consulté

How to Handle Both Form and JSON Data in a Single FastAPI Endpoint?

Comment créer un point de terminaison FastAPI pouvant accepter un formulaire ou un corps JSON ?

Dans FastAPI, vous pouvez créer un point de terminaison pouvant accepter un formulaire ou un corps JSON en utilisant différentes méthodes. Voici quelques options :

Option 1 : Utiliser une fonction de dépendance

Cette option implique la création d'une fonction de dépendance qui vérifie la valeur de l'en-tête de la requête Content-Type et analyse le corps à l'aide des méthodes de Starlette. , en conséquence.

<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>
Copier après la connexion

Option 2 : Définir des points de terminaison séparés

Une autre option consiste à avoir un seul point de terminaison et à définir vos paramètres de données de fichier et/ou de formulaire comme facultatifs. Si l'un des paramètres reçoit des valeurs, cela signifie que la requête était soit application/x-www-form-urlencoded, soit multipart/form-data. Sinon, il s'agissait probablement d'une requête 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>
Copier après la connexion

Option 3 : Utiliser un middleware

Vous pouvez également utiliser un middleware pour vérifier la requête entrante et la rediriger vers /submitJSON ou / Point de terminaison submitForm, en fonction du type de contenu de la requête.

<code class="python">from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.middleware(&quot;http&quot;)
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>
Copier après la connexion

Test des options

Vous pouvez tester les options ci-dessus à l'aide de la bibliothèque de requêtes de Python :

<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>
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal