Movatterモバイル変換


[0]ホーム

URL:


Saltar a contenido
Join theFastAPI Cloud waiting list 🚀
Follow@fastapi onX (Twitter) to stay updated
FollowFastAPI onLinkedIn to stay updated
Subscribe to theFastAPI and friends newsletter 🎉
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor

Cuerpo - Modelos Anidados

🌐 Traducción por IA y humanos

Esta traducción fue hecha por IA guiada por humanos. 🤝

Podría tener errores al interpretar el significado original, o sonar poco natural, etc. 🤖

Puedes mejorar esta traducciónayudándonos a guiar mejor al LLM de IA.

Versión en inglés

ConFastAPI, puedes definir, validar, documentar y usar modelos anidados de manera arbitraria (gracias a Pydantic).

Campos de lista

Puedes definir un atributo como un subtipo. Por ejemplo, unalist en Python:

fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:list=[]@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

Esto hará quetags sea una lista, aunque no declare el tipo de los elementos de la lista.

Campos de lista con parámetro de tipo

Pero Python tiene una forma específica de declarar listas con tipos internos, o "parámetros de tipo":

Declarar unalist con un parámetro de tipo

Para declarar tipos que tienen parámetros de tipo (tipos internos), comolist,dict,tuple,pasa el/los tipo(s) interno(s) como "parámetros de tipo" usando corchetes:[ y]

my_list:list[str]

Eso es toda la sintaxis estándar de Python para declaraciones de tipo.

Usa esa misma sintaxis estándar para atributos de modelos con tipos internos.

Así, en nuestro ejemplo, podemos hacer quetags sea específicamente una "lista de strings":

fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:list[str]=[]@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

Tipos de conjunto

Pero luego pensamos en ello, y nos damos cuenta de que los tags no deberían repetirse, probablemente serían strings únicos.

Y Python tiene un tipo de datos especial para conjuntos de elementos únicos, elset.

Entonces podemos declarartags como un conjunto de strings:

fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:set[str]=set()@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

Con esto, incluso si recibes un request con datos duplicados, se convertirá en un conjunto de elementos únicos.

Y siempre que emitas esos datos, incluso si la fuente tenía duplicados, se emitirá como un conjunto de elementos únicos.

Y también se anotará/documentará en consecuencia.

Modelos Anidados

Cada atributo de un modelo Pydantic tiene un tipo.

Pero ese tipo puede ser en sí mismo otro modelo Pydantic.

Así que, puedes declarar "objetos" JSON anidados profundamente con nombres de atributos específicos, tipos y validaciones.

Todo eso, de manera arbitraria.

Definir un submodelo

Por ejemplo, podemos definir un modeloImage:

fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classImage(BaseModel):url:strname:strclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:set[str]=set()image:Image|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

Usar el submodelo como tipo

Y luego podemos usarlo como el tipo de un atributo:

fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classImage(BaseModel):url:strname:strclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:set[str]=set()image:Image|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

Esto significaría queFastAPI esperaría un cuerpo similar a:

{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2,"tags":["rock","metal","bar"],"image":{"url":"http://example.com/baz.jpg","name":"The Foo live"}}

Nuevamente, haciendo solo esa declaración, conFastAPI obtienes:

  • Soporte de editor (autocompletado, etc.), incluso para modelos anidados
  • Conversión de datos
  • Validación de datos
  • Documentación automática

Tipos especiales y validación

Además de tipos singulares normales comostr,int,float, etc., puedes usar tipos singulares más complejos que heredan destr.

Para ver todas las opciones que tienes, revisa elOverview de Tipos de Pydantic. Verás algunos ejemplos en el siguiente capítulo.

Por ejemplo, como en el modeloImage tenemos un campourl, podemos declararlo como una instance deHttpUrl de Pydantic en lugar de unstr:

fromfastapiimportFastAPIfrompydanticimportBaseModel,HttpUrlapp=FastAPI()classImage(BaseModel):url:HttpUrlname:strclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:set[str]=set()image:Image|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

El string será verificado para ser una URL válida, y documentado en JSON Schema / OpenAPI como tal.

Atributos con listas de submodelos

También puedes usar modelos Pydantic como subtipos delist,set, etc.:

fromfastapiimportFastAPIfrompydanticimportBaseModel,HttpUrlapp=FastAPI()classImage(BaseModel):url:HttpUrlname:strclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:set[str]=set()images:list[Image]|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

Esto esperará (convertirá, validará, documentará, etc.) un cuerpo JSON como:

{"name":"Foo","description":"The pretender","price":42.0,"tax":3.2,"tags":["rock","metal","bar"],"images":[{"url":"http://example.com/baz.jpg","name":"The Foo live"},{"url":"http://example.com/dave.jpg","name":"The Baz"}]}

Información

Nota cómo la claveimages ahora tiene una lista de objetos de imagen.

Modelos anidados profundamente

Puedes definir modelos anidados tan profundamente como desees:

fromfastapiimportFastAPIfrompydanticimportBaseModel,HttpUrlapp=FastAPI()classImage(BaseModel):url:HttpUrlname:strclassItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonetags:set[str]=set()images:list[Image]|None=NoneclassOffer(BaseModel):name:strdescription:str|None=Noneprice:floatitems:list[Item]@app.post("/offers/")asyncdefcreate_offer(offer:Offer):returnoffer

Información

Observa cómoOffer tiene una lista deItems, que a su vez tienen una lista opcional deImages

Cuerpos de listas puras

Si el valor superior del cuerpo JSON que esperas es unarray JSON (unalist en Python), puedes declarar el tipo en el parámetro de la función, al igual que en los modelos Pydantic:

images:list[Image]

como en:

fromfastapiimportFastAPIfrompydanticimportBaseModel,HttpUrlapp=FastAPI()classImage(BaseModel):url:HttpUrlname:str@app.post("/images/multiple/")asyncdefcreate_multiple_images(images:list[Image]):returnimages

Soporte de editor en todas partes

Y obtienes soporte de editor en todas partes.

Incluso para elementos dentro de listas:

No podrías obtener este tipo de soporte de editor si estuvieras trabajando directamente condict en lugar de modelos Pydantic.

Pero tampoco tienes que preocuparte por ellos, losdicts entrantes se convierten automáticamente y tu salida se convierte automáticamente a JSON también.

Cuerpos dedicts arbitrarios

También puedes declarar un cuerpo como undict con claves de algún tipo y valores de algún otro tipo.

De esta manera, no tienes que saber de antemano cuáles son los nombres válidos de campo/atributo (como sería el caso con modelos Pydantic).

Esto sería útil si deseas recibir claves que aún no conoces.


Otro caso útil es cuando deseas tener claves de otro tipo (por ejemplo,int).

Eso es lo que vamos a ver aquí.

En este caso, aceptarías cualquierdict siempre que tenga clavesint con valoresfloat:

fromfastapiimportFastAPIapp=FastAPI()@app.post("/index-weights/")asyncdefcreate_index_weights(weights:dict[int,float]):returnweights

Consejo

Ten en cuenta que JSON solo admitestr como claves.

Pero Pydantic tiene conversión automática de datos.

Esto significa que, aunque tus clientes de API solo pueden enviar strings como claves, mientras esos strings contengan enteros puros, Pydantic los convertirá y validará.

Y eldict que recibas comoweights tendrá realmente clavesint y valoresfloat.

Resumen

ConFastAPI tienes la máxima flexibilidad proporcionada por los modelos Pydantic, manteniendo tu código simple, corto y elegante.

Pero con todos los beneficios:

  • Soporte de editor (¡autocompletado en todas partes!)
  • Conversión de datos (también conocido como parsing/serialización)
  • Validación de datos
  • Documentación del esquema
  • Documentación automática

[8]ページ先頭

©2009-2026 Movatter.jp