Estoy trabajando en un sitio web donde el frontend se realiza en React y el backend en Python con FastAPI. Hice un formulario que toma algunos datos y los envía al backend con axios. Se parece a esto
{ name='Jonathan', aliases=["Johnny"], birthdate='2-15-1980', gender='male', height=178 weight=90 nationalities=["American", "French"], occupations=["Programmer", "Comedian"], status='single', images=[ {'attachment': FileList, 'location': 'Berlin', 'date': '10-14-2019' } ] }Sin embargo, cuando lo envíe. FastApi parece eliminar las imágenes del formulario.
name='Jonathan', aliases=["Johnny"], birthdate='2-15-1980', gender='male', height=178 weight=90 nationalities=["American", "French"], occupations=["Programmer", "Comedian"], status='single', images=[ {'attachment': {'0': {}}, 'location': 'Berlin', 'date': '10-14-2019'} ]Así es como se ve la ruta actualmente
@router.post("/register/user") def register_user(user_data: UserCreate): print(user_data)No estoy completamente seguro de lo que está pasando. Supongo que tiene algo que ver con la forma en que se envían los datos y su encriptación. Estoy en un callejón sin salida aquí. Gracias por adelantado.
Editar: así es como se ve el esquema UserCreate
class CharacterCreate(BaseModel): name: str aliases: list birthdate: Optional[str] gender: str height: Optional[float] weight: Optional[float] nationalities: Optional[set[str]] occupations: Optional[set[str]] status: str images: Optional[list]Según la documentación , no puede tener tanto JSON como Files / form-data en la misma solicitud, ya que el cuerpo está codificado usando multipart/form-data (cuando se incluyen archivos) o application/x-www-form-urlencoded (si solo se incluyen los datos del Form ) en lugar de application/json . Echa un vistazo a esta respuesta .
Por lo tanto, una forma de resolver esto es usar un solo parámetro para contener los diversos "metadatos" y tener un segundo para los archivos/imágenes. Al usar la Dependency Injection , puede comparar los datos recibidos con el modelo Pydantic usando el método parse_raw , antes de continuar con el punto final. Si se lanza un ValidationError , se debe generar una HTTPException ( HTTP_422_UNPROCESSABLE_ENTITY ), incluidos los errores. El ejemplo de trabajo se da a continuación. Alternativamente, eche un vistazo al Método 4 en esta respuesta .
app.py
from fastapi import FastAPI, Form, File, UploadFile, status import pydantic from pydantic import BaseModel from typing import Optional, List from fastapi.exceptions import HTTPException from fastapi.encoders import jsonable_encoder from fastapi import Depends app = FastAPI() class User(BaseModel): name: str aliases: List[str] height: Optional[float] weight: Optional[float] def checker(data: str = Form(...)): try: user = User.parse_raw(data) except pydantic.ValidationError as e: raise HTTPException(detail=jsonable_encoder(e.errors()), status_code=status.HTTP_422_UNPROCESSABLE_ENTITY) return user @app.post("/submit") def submit(user: User = Depends(checker), files: List[UploadFile] = File(...)): return {"User": user, "Uploaded Files": [file.filename for file in files]}prueba.py
import requests url = 'http://127.0.0.1:8000/submit' files = [('files', open('test_files/a.txt', 'rb')), ('files', open('test_files/b.txt', 'rb'))] data = {'data' : '{"name": "foo", "aliases": ["alias_1", "alias_2"], "height": 1.80, "weight": 80.5}'} resp = requests.post(url=url, data=data, files=files) print(resp.json())