Hace unas tres semanas salió a la luz una de las características más esperadas de FastAPI. Al menos cuando hablamos de Pydantic Models FastAPI.
Sí, me refiero a la capacidad de utilizar modelos Pydantic para asignar sus parámetros de consulta.
Entonces, en esta publicación, intentaré mostrártelos todos. puede y ? ¿Qué no puedo hacer con este tema?:
Lo primero que debe hacer para comenzar a mapear sus parámetros de consulta con Pydantic es asegurarse de que está utilizando FastAPI versión 0.115.0.
Después de esto, siempre puedes ir a los documentos de FastAPI para verificar lo que ya está disponible. Sebastián y los miembros del equipo hacen un muy, muy buen trabajo manteniendo los documentos actualizados e informativos ✨.
Comencemos con algunos ejemplos sobre cómo solíamos asignar parámetros de consulta en FastAPI. ?
La forma más sencilla de hacerlo sería:
from fastapi import FastAPI app = FastAPI() @app.get("/") async def search( limit: int | None = 10, skip: int | None = 1, filter: str | None = None ): return { "limit": limit, "skip": skip, "filter": filter }
Y ahora puedes simplemente llamar:
GET http://localhost:8000/?limit=42&skip=12&filter=banana
Pero si identificamos que estos parámetros de consulta se usarían en otras rutas, lo aislaríamos con algo como:
from typing import Any from fastapi import Depends, FastAPI, Query app = FastAPI() async def pagination_query_string( limit: int | None = Query(10, ge=5, le=100), skip: int | None = Query(1, ge=1), filter: str | None = Query(None) ) -> dict[str, Any]: return { "limit": limit, "skip": skip, "filter": filter } @app.get("/") async def search(q: dict[str, Any] = Depends(pagination_query_string)): return q
O como estamos usando Pydantic para mapear nuestros modelos, con solo una pequeña refactorización obtendríamos:
from fastapi import Depends, FastAPI, Query from pydantic import BaseModel app = FastAPI() class PaginationQueryString(BaseModel): limit: int | None = 10 skip: int | None = 1 filter: str | None = None async def pagination_query_string( limit: int | None = Query(10, ge=5, le=100), skip: int | None = Query(1, ge=1), filter: str | None = Query(None) ) -> PaginationQueryString: return PaginationQueryString( limit=limit, skip=skip, filter=filter ) @app.get("/") async def search(q: PaginationQueryString = Depends(pagination_query_string)): return q
Ahora, si queremos obtener nuestra cadena de consulta, no necesitamos crear una función y luego agregarla como una dependencia. Simplemente podemos decirle a FastAPI que queremos un objeto de tipo PaginationQueryString y que es una cadena de consulta:
from typing import Annotated from fastapi import FastAPI, Query from pydantic import BaseModel app = FastAPI() class PaginationQueryString(BaseModel): limit: int | None = 10 skip: int | None = 1 filter: str | None = None @app.get("/") async def search(q: Annotated[PaginationQueryString, Query()]): return q
Fácil, ¿verdad? ?
Al menos en la versión 0.115.0, no funciona muy bien con modelos anidados.
Probemos algo como:
from typing import Annotated from fastapi import FastAPI, Query from pydantic import BaseModel app = FastAPI() class Filter(BaseModel): name: str | None = None age: int | None = None nickname: str | None = None class PaginationQueryString(BaseModel): limit: int | None = 10 skip: int | None = 1 filter: Filter | None = None @app.get("/") async def search(q: Annotated[PaginationQueryString, Query()]): return q
Si lo llamamos como antes:
GET http://localhost:8000/?limit=42&skip=12&filter=chocolate
Recibiremos un error que nos indica que el filtro es un objeto:
{ "detail": [ { "type": "model_attributes_type", "loc": [ "query", "filter" ], "msg": "Input should be a valid dictionary or object to extract fields from", "input": "chocolate" } ] }
¡Al menos ahora mismo, es absolutamente correcto! Cambiamos nuestro filtro para que sea un modelo Pydantic, no una cadena. Pero si intentamos convertirlo a un diccionario:
http://localhost:8000/?limit=42&skip=12&filter={"name": "Rafael", "age": 38, "nickname": "ceb10n"}
FastAPI nos dirá que el filtro debe ser un diccionario válido:
{ "detail": [ { "type": "model_attributes_type", "loc": [ "query", "filter" ], "msg": "Input should be a valid dictionary or object to extract fields from", "input": "{\"name\": \"Rafael\", \"age\": 38, \"nickname\": \"ceb10n\"}" } ] }
Esto sucede porque FastAPI dependerá de QueryParams de Starlette, que le dará una cadena a FastAPI, no un dict. Y al menos en la versión 0.115.0, esto te dará un error.
Es bastante simple:
✅ ¿Tiene cadenas de consulta simples que no necesitan ningún objeto anidado sofisticado y elaborado? ¡Úselo! ?
❌ ¿Creaste una cadena de consulta anidada compleja? ¿Aún no lo usas?. (Y tal vez debería intentar reconsiderar sus cadenas de consulta. ¿Cuanto más simples, mejor?)
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3