Files
fastapi/docs/es/docs/tutorial/query-params-str-validations.md
Sebastián Ramírez a2912ffa26 🌐 Update translations for es (update-outdated) (#14686)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-01-11 00:41:20 +01:00

18 KiB

Parámetros de Query y Validaciones de String

FastAPI te permite declarar información adicional y validación para tus parámetros.

Tomemos esta aplicación como ejemplo:

{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}

El parámetro de query q es de tipo str | None, lo que significa que es de tipo str pero también podría ser None, y de hecho, el valor por defecto es None, así que FastAPI sabrá que no es requerido.

/// note | Nota

FastAPI sabrá que el valor de q no es requerido por el valor por defecto = None.

Tener str | None permitirá que tu editor te dé un mejor soporte y detecte errores.

///

Validaciones adicionales

Vamos a hacer que, aunque q sea opcional, siempre que se proporcione, su longitud no exceda los 50 caracteres.

Importar Query y Annotated

Para lograr eso, primero importa:

  • Query desde fastapi
  • Annotated desde typing

{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}

/// info | Información

FastAPI añadió soporte para Annotated (y empezó a recomendarlo) en la versión 0.95.0.

Si tienes una versión más antigua, obtendrás errores al intentar usar Annotated.

Asegúrate de Actualizar la versión de FastAPI{.internal-link target=_blank} a al menos 0.95.1 antes de usar Annotated.

///

Usar Annotated en el tipo del parámetro q

¿Recuerdas que te dije antes que Annotated puede usarse para agregar metadatos a tus parámetros en la Introducción a Tipos de Python{.internal-link target=_blank}?

Ahora es el momento de usarlo con FastAPI. 🚀

Teníamos esta anotación de tipo:

//// tab | Python 3.10+

q: str | None = None

////

//// tab | Python 3.9+

q: Union[str, None] = None

////

Lo que haremos es envolver eso con Annotated, para que se convierta en:

//// tab | Python 3.10+

q: Annotated[str | None] = None

////

//// tab | Python 3.9+

q: Annotated[Union[str, None]] = None

////

Ambas versiones significan lo mismo, q es un parámetro que puede ser un str o None, y por defecto, es None.

Ahora vamos a lo divertido. 🎉

Agregar Query a Annotated en el parámetro q

Ahora que tenemos este Annotated donde podemos poner más información (en este caso algunas validaciones adicionales), agrega Query dentro de Annotated, y establece el parámetro max_length a 50:

{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}

Nota que el valor por defecto sigue siendo None, por lo que el parámetro sigue siendo opcional.

Pero ahora, al tener Query(max_length=50) dentro de Annotated, le estamos diciendo a FastAPI que queremos que tenga validación adicional para este valor, queremos que tenga un máximo de 50 caracteres. 😎

/// tip | Consejo

Aquí estamos usando Query() porque este es un parámetro de query. Más adelante veremos otros como Path(), Body(), Header(), y Cookie(), que también aceptan los mismos argumentos que Query().

///

FastAPI ahora:

  • Validará los datos asegurándose de que la longitud máxima sea de 50 caracteres
  • Mostrará un error claro para el cliente cuando los datos no sean válidos
  • Documentará el parámetro en el OpenAPI esquema path operation (así aparecerá en la UI de documentación automática)

Alternativa (antigua): Query como valor por defecto

Versiones anteriores de FastAPI (antes de 0.95.0) requerían que usaras Query como el valor por defecto de tu parámetro, en lugar de ponerlo en Annotated, hay una alta probabilidad de que veas código usándolo alrededor, así que te lo explicaré.

/// tip | Consejo

Para nuevo código y siempre que sea posible, usa Annotated como se explicó arriba. Hay múltiples ventajas (explicadas a continuación) y no hay desventajas. 🍰

///

Así es como usarías Query() como el valor por defecto de tu parámetro de función, estableciendo el parámetro max_length a 50:

{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}

Como en este caso (sin usar Annotated) debemos reemplazar el valor por defecto None en la función con Query(), ahora necesitamos establecer el valor por defecto con el parámetro Query(default=None), esto sirve al mismo propósito de definir ese valor por defecto (al menos para FastAPI).

Entonces:

q: str | None = Query(default=None)

...hace que el parámetro sea opcional, con un valor por defecto de None, lo mismo que:

q: str | None = None

Pero la versión con Query lo declara explícitamente como un parámetro de query.

Luego, podemos pasar más parámetros a Query. En este caso, el parámetro max_length que se aplica a los strings:

q: str | None = Query(default=None, max_length=50)

Esto validará los datos, mostrará un error claro cuando los datos no sean válidos, y documentará el parámetro en el esquema del path operation de OpenAPI.

Query como valor por defecto o en Annotated

Ten en cuenta que cuando uses Query dentro de Annotated no puedes usar el parámetro default para Query.

En su lugar utiliza el valor por defecto real del parámetro de la función. De lo contrario, sería inconsistente.

Por ejemplo, esto no está permitido:

q: Annotated[str, Query(default="rick")] = "morty"

...porque no está claro si el valor por defecto debería ser "rick" o "morty".

Así que utilizarías (preferentemente):

q: Annotated[str, Query()] = "rick"

...o en code bases más antiguas encontrarás:

q: str = Query(default="rick")

Ventajas de Annotated

Usar Annotated es recomendado en lugar del valor por defecto en los parámetros de función, es mejor por múltiples razones. 🤓

El valor por defecto del parámetro de función es el valor real por defecto, eso es más intuitivo con Python en general. 😌

Podrías llamar a esa misma función en otros lugares sin FastAPI, y funcionaría como se espera. Si hay un parámetro requerido (sin un valor por defecto), tu editor te avisará con un error, Python también se quejará si lo ejecutas sin pasar el parámetro requerido.

Cuando no usas Annotated y en su lugar usas el estilo de valor por defecto (antiguo), si llamas a esa función sin FastAPI en otros lugares, tienes que recordar pasar los argumentos a la función para que funcione correctamente, de lo contrario, los valores serán diferentes de lo que esperas (por ejemplo, QueryInfo o algo similar en lugar de str). Y tu editor no se quejará, y Python no se quejará al ejecutar esa función, solo cuando los errores dentro de las operaciones hagan que funcione incorrectamente.

Dado que Annotated puede tener más de una anotación de metadato, ahora podrías incluso usar la misma función con otras herramientas, como Typer. 🚀

Agregar más validaciones

También puedes agregar un parámetro min_length:

{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}

Agregar expresiones regulares

Puedes definir una expresión regular pattern que el parámetro debe coincidir:

{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}

Este patrón específico de expresión regular comprueba que el valor recibido del parámetro:

  • ^: comienza con los siguientes caracteres, no tiene caracteres antes.
  • fixedquery: tiene el valor exacto fixedquery.
  • $: termina allí, no tiene más caracteres después de fixedquery.

Si te sientes perdido con todas estas ideas de "expresión regular", no te preocupes. Son un tema difícil para muchas personas. Aún puedes hacer muchas cosas sin necesitar expresiones regulares todavía.

Ahora sabes que cuando las necesites puedes usarlas en FastAPI.

Valores por defecto

Puedes, por supuesto, usar valores por defecto diferentes de None.

Digamos que quieres declarar el parámetro de query q para que tenga un min_length de 3, y para que tenga un valor por defecto de "fixedquery":

{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}

/// note | Nota

Tener un valor por defecto de cualquier tipo, incluyendo None, hace que el parámetro sea opcional (no requerido).

///

Parámetros requeridos

Cuando no necesitamos declarar más validaciones o metadatos, podemos hacer que el parámetro de query q sea requerido simplemente no declarando un valor por defecto, como:

q: str

en lugar de:

q: str | None = None

Pero ahora lo estamos declarando con Query, por ejemplo, como:

q: Annotated[str | None, Query(min_length=3)] = None

Así que, cuando necesites declarar un valor como requerido mientras usas Query, simplemente puedes no declarar un valor por defecto:

{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}

Requerido, puede ser None

Puedes declarar que un parámetro puede aceptar None, pero que aún así es requerido. Esto obligaría a los clientes a enviar un valor, incluso si el valor es None.

Para hacer eso, puedes declarar que None es un tipo válido pero simplemente no declarar un valor por defecto:

{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}

Lista de parámetros de Query / múltiples valores

Cuando defines un parámetro de query explícitamente con Query también puedes declararlo para recibir una lista de valores, o dicho de otra manera, para recibir múltiples valores.

Por ejemplo, para declarar un parámetro de query q que puede aparecer varias veces en la URL, puedes escribir:

{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}

Entonces, con una URL como:

http://localhost:8000/items/?q=foo&q=bar

recibirías los múltiples valores de los query parameters q (foo y bar) en una list de Python dentro de tu path operation function, en el parámetro de función q.

Entonces, el response a esa URL sería:

{
  "q": [
    "foo",
    "bar"
  ]
}

/// tip | Consejo

Para declarar un parámetro de query con un tipo de list, como en el ejemplo anterior, necesitas usar explícitamente Query, de lo contrario sería interpretado como un request body.

///

La documentación interactiva de API se actualizará en consecuencia, para permitir múltiples valores:

Lista de parámetros de Query / múltiples valores con valores por defecto

También puedes definir un valor por defecto list de valores si no se proporciona ninguno:

{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}

Si vas a:

http://localhost:8000/items/

el valor por defecto de q será: ["foo", "bar"] y tu response será:

{
  "q": [
    "foo",
    "bar"
  ]
}

Usando solo list

También puedes usar list directamente en lugar de list[str]:

{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}

/// note | Nota

Ten en cuenta que en este caso, FastAPI no comprobará el contenido de la lista.

Por ejemplo, list[int] comprobaría (y documentaría) que el contenido de la lista son enteros. Pero list sola no lo haría.

///

Declarar más metadatos

Puedes agregar más información sobre el parámetro.

Esa información se incluirá en el OpenAPI generado y será utilizada por las interfaces de usuario de documentación y herramientas externas.

/// note | Nota

Ten en cuenta que diferentes herramientas podrían tener diferentes niveles de soporte de OpenAPI.

Algunas de ellas podrían no mostrar toda la información extra declarada todavía, aunque en la mayoría de los casos, la funcionalidad faltante ya está planificada para desarrollo.

///

Puedes agregar un title:

{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}

Y una description:

{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}

Alias para parámetros

Imagina que quieres que el parámetro sea item-query.

Como en:

http://127.0.0.1:8000/items/?item-query=foobaritems

Pero item-query no es un nombre de variable válido en Python.

Lo más cercano sería item_query.

Pero aún necesitas que sea exactamente item-query...

Entonces puedes declarar un alias, y ese alias será usado para encontrar el valor del parámetro:

{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}

Declarar parámetros obsoletos

Ahora digamos que ya no te gusta este parámetro.

Tienes que dejarlo allí por un tiempo porque hay clientes usándolo, pero quieres que la documentación lo muestre claramente como deprecated.

Luego pasa el parámetro deprecated=True a Query:

{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}

La documentación lo mostrará así:

Excluir parámetros de OpenAPI

Para excluir un parámetro de query del esquema de OpenAPI generado (y por lo tanto, de los sistemas de documentación automática), establece el parámetro include_in_schema de Query a False:

{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}

Validación personalizada

Podría haber casos donde necesites hacer alguna validación personalizada que no puede hacerse con los parámetros mostrados arriba.

En esos casos, puedes usar una función validadora personalizada que se aplique después de la validación normal (por ejemplo, después de validar que el valor es un str).

Puedes lograr eso usando AfterValidator de Pydantic dentro de Annotated.

/// tip | Consejo

Pydantic también tiene BeforeValidator y otros. 🤓

///

Por ejemplo, este validador personalizado comprueba que el ID del ítem empiece con isbn- para un número de libro ISBN o con imdb- para un ID de URL de película de IMDB:

{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}

/// info | Información

Esto está disponible con Pydantic versión 2 o superior. 😎

///

/// tip | Consejo

Si necesitas hacer cualquier tipo de validación que requiera comunicarte con algún componente externo, como una base de datos u otra API, deberías usar Dependencias de FastAPI, las aprenderás más adelante.

Estos validadores personalizados son para cosas que pueden comprobarse solo con los mismos datos provistos en el request.

///

Entiende ese código

El punto importante es solo usar AfterValidator con una función dentro de Annotated. Si quieres, sáltate esta parte. 🤸


Pero si te da curiosidad este ejemplo de código específico y sigues entretenido, aquí tienes algunos detalles extra.

String con value.startswith()

¿Lo notaste? un string usando value.startswith() puede recibir una tupla, y comprobará cada valor en la tupla:

{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}

Un ítem aleatorio

Con data.items() obtenemos un objeto iterable con tuplas que contienen la clave y el valor para cada elemento del diccionario.

Convertimos este objeto iterable en una list propiamente dicha con list(data.items()).

Luego con random.choice() podemos obtener un valor aleatorio de la lista, así que obtenemos una tupla con (id, name). Será algo como ("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy").

Luego asignamos esos dos valores de la tupla a las variables id y name.

Así, si el usuario no proporcionó un ID de ítem, aún recibirá una sugerencia aleatoria.

...hacemos todo esto en una sola línea simple. 🤯 ¿No te encanta Python? 🐍

{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}

Recapitulación

Puedes declarar validaciones y metadatos adicionales para tus parámetros.

Validaciones genéricas y metadatos:

  • alias
  • title
  • description
  • deprecated

Validaciones específicas para strings:

  • min_length
  • max_length
  • pattern

Validaciones personalizadas usando AfterValidator.

En estos ejemplos viste cómo declarar validaciones para valores de tipo str.

Mira los siguientes capítulos para aprender cómo declarar validaciones para otros tipos, como números.