Sync fastapi docs from 7cb06f36 on 2026-07-11

This commit is contained in:
The Librarian
2026-07-11 04:00:12 +00:00
parent 2c5483ee1c
commit d71a936809
1032 changed files with 12357 additions and 6438 deletions
+2 -2
View File
@@ -197,7 +197,7 @@ Aquí algunas cosas envueltas en elementos HTML "abbr" (algunas son inventadas):
### El abbr da una frase completa y una explicación { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbr title="Mozilla Developer Network - Red de Desarrolladores de Mozilla: documentación para desarrolladores, escrita por la gente de Firefox">MDN</abbr>
* <abbr title="Input/Output - Entrada/Salida: lectura o escritura de disco, comunicaciones de red.">I/O</abbr>.
* <abbr title="Input/Output - I/O: lectura o escritura de disco, comunicaciones de red.">I/O</abbr>.
////
@@ -464,7 +464,7 @@ Para instrucciones específicas del idioma, mira p. ej. la sección `### Heading
* el middleware
* la aplicación móvil
* el módulo
* el mount
* el mounting
* la red
* el origen
* el override
@@ -34,7 +34,7 @@ Ten en cuenta que debes devolver el `JSONResponse` directamente.
///
/// info | Información
/// note | Nota
La clave `model` no es parte de OpenAPI.
@@ -183,7 +183,7 @@ Nota que debes devolver la imagen usando un `FileResponse` directamente.
///
/// info | Información
/// note | Nota
A menos que especifiques un media type diferente explícitamente en tu parámetro `responses`, FastAPI asumirá que el response tiene el mismo media type que la clase de response principal (por defecto `application/json`).
@@ -1,5 +1,6 @@
# Códigos de Estado Adicionales { #additional-status-codes }
Por defecto, **FastAPI** devolverá los responses usando un `JSONResponse`, colocando el contenido que devuelves desde tu *path operation* dentro de ese `JSONResponse`.
Usará el código de estado por defecto o el que configures en tu *path operation*.
@@ -10,7 +10,7 @@ Imaginemos que queremos tener una dependencia que revise si el parámetro de que
Pero queremos poder parametrizar ese contenido fijo.
## Una *instance* "callable" { #a-callable-instance }
## Una instance "callable" { #a-callable-instance }
En Python hay una forma de hacer que una instance de una clase sea un "callable".
@@ -98,7 +98,7 @@ Por ejemplo, si tenías una sesión de base de datos en una dependencia con `yie
Este comportamiento se revirtió en la 0.118.0, para hacer que el código de salida después de `yield` se ejecute después de que la response sea enviada.
/// info | Información
/// note | Nota
Como verás abajo, esto es muy similar al comportamiento anterior a la versión 0.106.0, pero con varias mejoras y arreglos de bugs para casos límite.
@@ -108,7 +108,7 @@ Como verás abajo, esto es muy similar al comportamiento anterior a la versión
Hay algunos casos de uso con condiciones específicas que podrían beneficiarse del comportamiento antiguo de ejecutar el código de salida de dependencias con `yield` antes de enviar la response.
Por ejemplo, imagina que tienes código que usa una sesión de base de datos en una dependencia con `yield` solo para verificar un usuario, pero la sesión de base de datos no se vuelve a usar en la *path operation function*, solo en la dependencia, y la response tarda mucho en enviarse, como un `StreamingResponse` que envía datos lentamente, pero que por alguna razón no usa la base de datos.
Por ejemplo, imagina que tienes código que usa una sesión de base de datos en una dependencia con `yield` solo para verificar un usuario, pero la sesión de base de datos no se vuelve a usar en la *path operation function*, solo en la dependencia, **y** la response tarda mucho en enviarse, como un `StreamingResponse` que envía datos lentamente, pero que por alguna razón no usa la base de datos.
En este caso, la sesión de base de datos se mantendría hasta que la response termine de enviarse, pero si no la usas, entonces no sería necesario mantenerla.
+4 -4
View File
@@ -24,7 +24,7 @@ Si declaras un [Response Model](../tutorial/response-model.md) FastAPI lo usará
Si no declaras un response model, FastAPI usará el `jsonable_encoder` explicado en [Codificador Compatible con JSON](../tutorial/encoder.md) y lo pondrá en un `JSONResponse`.
Si declaras un `response_class` con un media type JSON (`application/json`), como es el caso con `JSONResponse`, los datos que devuelvas se convertirán automáticamente (y serán filtrados) con cualquier `response_model` de Pydantic que hayas declarado en el *path operation decorator*. Pero los datos no se serializarán a bytes JSON con Pydantic, en su lugar se convertirán con el `jsonable_encoder` y luego se pasarán a la clase `JSONResponse`, que los serializará a bytes usando la librería JSON estándar de Python.
Si declaras un `response_class` con un media type JSON (`application/json`), como es el caso con `JSONResponse`, los datos que devuelvas se convertirán automáticamente (y serán filtrados) con cualquier `response_model` de Pydantic que hayas declarado en el *path operation decorator*. Pero los datos no se serializarán a bytes JSON con Pydantic, en su lugar se convertirán con el `jsonable_encoder` y luego se pasarán a la clase `JSONResponse`, que los serializará a bytes usando el paquete JSON estándar de Python.
### Rendimiento JSON { #json-performance }
@@ -41,7 +41,7 @@ Para devolver un response con HTML directamente desde **FastAPI**, usa `HTMLResp
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
/// info | Información
/// note | Nota
El parámetro `response_class` también se utilizará para definir el "media type" del response.
@@ -65,7 +65,7 @@ Una `Response` devuelta directamente por tu *path operation function* no se docu
///
/// info | Información
/// note | Nota
Por supuesto, el `Content-Type` header real, el código de estado, etc., provendrán del objeto `Response` que devolviste.
@@ -181,7 +181,7 @@ Toma un generador `async` o un generador/iterador normal (una función con `yiel
Una tarea `async` solo puede cancelarse cuando llega a un `await`. Si no hay `await`, el generador (función con `yield`) no se puede cancelar correctamente y puede seguir ejecutándose incluso después de solicitar la cancelación.
Como este pequeño ejemplo no necesita ninguna sentencia `await`, añadimos un `await anyio.sleep(0)` para darle al loop de eventos la oportunidad de manejar la cancelación.
Como este pequeño ejemplo no necesita ninguna statement `await`, añadimos un `await anyio.sleep(0)` para darle al loop de eventos la oportunidad de manejar la cancelación.
Esto sería aún más importante con streams grandes o infinitos.
+2 -2
View File
@@ -18,7 +18,7 @@ Y por supuesto, soporta lo mismo:
Esto funciona de la misma manera que con los modelos de Pydantic. Y en realidad se logra de la misma manera internamente, utilizando Pydantic.
/// info | Información
/// note | Nota
Ten en cuenta que los dataclasses no pueden hacer todo lo que los modelos de Pydantic pueden hacer.
@@ -82,7 +82,7 @@ En ese caso, simplemente puedes intercambiar los `dataclasses` estándar con `py
Puedes combinar `dataclasses` con otras anotaciones de tipos en muchas combinaciones diferentes para formar estructuras de datos complejas.
Revisa las anotaciones en el código arriba para ver más detalles específicos.
Revisa los consejos de anotación en el código arriba para ver más detalles específicos.
## Aprende Más { #learn-more }
+5 -5
View File
@@ -6,13 +6,13 @@ De la misma manera, puedes definir lógica (código) que debería ser ejecutada
Debido a que este código se ejecuta antes de que la aplicación **comience** a tomar requests, y justo después de que **termine** de manejarlos, cubre todo el **lifespan** de la aplicación (la palabra "lifespan" será importante en un momento 😉).
Esto puede ser muy útil para configurar **recursos** que necesitas usar para toda la app, y que son **compartidos** entre requests, y/o que necesitas **limpiar** después. Por ejemplo, un pool de conexiones a una base de datos, o cargando un modelo de machine learning compartido.
Esto puede ser muy útil para configurar **recursos** que necesitas usar para toda la app, y que son **compartidos** entre requests, y/o que necesitas **limpiar** después. Por ejemplo, un pool de conexiones a una base de datos, o cargando un modelo de Machine Learning compartido.
## Caso de Uso { #use-case }
Empecemos con un ejemplo de **caso de uso** y luego veamos cómo resolverlo con esto.
Imaginemos que tienes algunos **modelos de machine learning** que quieres usar para manejar requests. 🤖
Imaginemos que tienes algunos **modelos de Machine Learning** que quieres usar para manejar requests. 🤖
Los mismos modelos son compartidos entre requests, por lo que no es un modelo por request, o uno por usuario o algo similar.
@@ -32,7 +32,7 @@ Creamos una función asíncrona `lifespan()` con `yield` así:
{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *}
Aquí estamos simulando la operación costosa de *startup* de cargar el modelo poniendo la función del (falso) modelo en el diccionario con modelos de machine learning antes del `yield`. Este código será ejecutado **antes** de que la aplicación **comience a tomar requests**, durante el *startup*.
Aquí estamos simulando la operación costosa de *startup* de cargar el modelo poniendo la función del (falso) modelo en el diccionario con modelos de Machine Learning antes del `yield`. Este código será ejecutado **antes** de que la aplicación **comience a tomar requests**, durante el *startup*.
Y luego, justo después del `yield`, quitaremos el modelo de memoria. Este código será ejecutado **después** de que la aplicación **termine de manejar requests**, justo antes del *shutdown*. Esto podría, por ejemplo, liberar recursos como la memoria o una GPU.
@@ -120,7 +120,7 @@ Para añadir una función que debería ejecutarse cuando la aplicación se esté
Aquí, la función manejadora del evento `shutdown` escribirá una línea de texto `"Application shutdown"` a un archivo `log.txt`.
/// info | Información
/// note | Nota
En la función `open()`, el `mode="a"` significa "añadir", por lo tanto, la línea será añadida después de lo que sea que esté en ese archivo, sin sobrescribir el contenido anterior.
@@ -152,7 +152,7 @@ Solo un detalle técnico para los nerds curiosos. 🤓
Por debajo, en la especificación técnica ASGI, esto es parte del [Protocolo de Lifespan](https://asgi.readthedocs.io/en/latest/specs/lifespan.html), y define eventos llamados `startup` y `shutdown`.
/// info | Información
/// note | Nota
Puedes leer más sobre los manejadores `lifespan` de Starlette en [la documentación de `Lifespan` de Starlette](https://www.starlette.dev/lifespan/).
+2 -17
View File
@@ -20,21 +20,6 @@ FastAPI genera automáticamente especificaciones **OpenAPI 3.1**, así que cualq
///
## Generadores de SDKs de sponsors de FastAPI { #sdk-generators-from-fastapi-sponsors }
Esta sección destaca soluciones **respaldadas por empresas** y **venture-backed** de compañías que sponsorean FastAPI. Estos productos ofrecen **funcionalidades adicionales** e **integraciones** además de SDKs generados de alta calidad.
Al ✨ [**sponsorear FastAPI**](../help-fastapi.md#sponsor-the-author) ✨, estas compañías ayudan a asegurar que el framework y su **ecosistema** se mantengan saludables y **sustentables**.
Su sponsorship también demuestra un fuerte compromiso con la **comunidad** de FastAPI (tú), mostrando que no solo les importa ofrecer un **gran servicio**, sino también apoyar un **framework robusto y próspero**, FastAPI. 🙇
Por ejemplo, podrías querer probar:
* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral)
* [liblab](https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi)
Algunas de estas soluciones también pueden ser open source u ofrecer niveles gratuitos, así que puedes probarlas sin un compromiso financiero. Hay otros generadores de SDK comerciales disponibles y se pueden encontrar en línea. 🤓
## Crea un SDK de TypeScript { #create-a-typescript-sdk }
Empecemos con una aplicación simple de FastAPI:
@@ -53,7 +38,7 @@ Puedes ver esos esquemas porque fueron declarados con los modelos en la app.
Esa información está disponible en el **OpenAPI schema** de la app, y luego se muestra en la documentación de la API.
Y esa misma información de los modelos que está incluida en OpenAPI es lo que puede usarse para **generar el código del cliente**.
Esa misma información de los modelos que está incluida en OpenAPI es lo que puede usarse para **generar el código del cliente**.
### Hey API { #hey-api }
@@ -132,7 +117,7 @@ Puedes **modificar** la forma en que estos operation IDs son **generados** para
En este caso tendrás que asegurarte de que cada operation ID sea **único** de alguna otra manera.
Por ejemplo, podrías asegurarte de que cada *path operation* tenga un tag, y luego generar el operation ID basado en el **tag** y el **name** de la *path operation* (el nombre de la función).
Por ejemplo, podrías asegurarte de que cada *path operation* tenga un tag, y luego generar el operation ID basado en el **tag** y el **nombre** de la *path operation* (el nombre de la función).
### Función personalizada para generar ID único { #custom-generate-unique-id-function }
+4 -4
View File
@@ -4,7 +4,7 @@ Si tu app necesita recibir y enviar datos JSON, pero necesitas incluir datos bin
## Base64 vs Archivos { #base64-vs-files }
Considera primero si puedes usar [Archivos en request](../tutorial/request-files.md) para subir datos binarios y [Response personalizada - FileResponse](./custom-response.md#fileresponse--fileresponse-) para enviar datos binarios, en lugar de codificarlos en JSON.
Considera primero si puedes usar [Archivos en request](../tutorial/request-files.md) para subir datos binarios y [Response personalizada - FileResponse](./custom-response.md#fileresponse) para enviar datos binarios, en lugar de codificarlos en JSON.
JSON solo puede contener strings codificados en UTF-8, así que no puede contener bytes crudos.
@@ -14,7 +14,7 @@ Usa base64 solo si definitivamente necesitas incluir datos binarios en JSON y no
## Pydantic `bytes` { #pydantic-bytes }
Puedes declarar un modelo de Pydantic con campos `bytes`, y luego usar `val_json_bytes` en la configuración del modelo para indicarle que use base64 para validar datos JSON de entrada; como parte de esa validación decodificará el string base64 en bytes.
Puedes declarar un modelo de Pydantic con campos `bytes`, y luego usar `val_json_bytes` en la configuración del modelo para indicarle que use base64 para *validar* datos JSON de entrada; como parte de esa validación decodificará el string base64 en bytes.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *}
@@ -52,12 +52,12 @@ Recibirás una response como:
## Pydantic `bytes` para datos de salida { #pydantic-bytes-for-output-data }
También puedes usar campos `bytes` con `ser_json_bytes` en la configuración del modelo para datos de salida, y Pydantic serializará los bytes como base64 al generar la response JSON.
También puedes usar campos `bytes` con `ser_json_bytes` en la configuración del modelo para datos de salida, y Pydantic *serializará* los bytes como base64 al generar la response JSON.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *}
## Pydantic `bytes` para datos de entrada y salida { #pydantic-bytes-for-input-and-output-data }
Y por supuesto, puedes usar el mismo modelo configurado para usar base64 para manejar tanto la entrada (*validate*) con `val_json_bytes` como la salida (*serialize*) con `ser_json_bytes` al recibir y enviar datos JSON.
Y por supuesto, puedes usar el mismo modelo configurado para usar base64 para manejar tanto la entrada (*validar*) con `val_json_bytes` como la salida (*serializar*) con `ser_json_bytes` al recibir y enviar datos JSON.
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *}
+3 -3
View File
@@ -4,7 +4,7 @@ Podrías crear una API con una *path operation* que podría desencadenar un requ
El proceso que ocurre cuando tu aplicación API llama a la *API externa* se llama un "callback". Porque el software que escribió el desarrollador externo envía un request a tu API y luego tu API hace un *callback*, enviando un request a una *API externa* (que probablemente fue creada por el mismo desarrollador).
En este caso, podrías querer documentar cómo esa API externa *debería* verse. Qué *path operation* debería tener, qué cuerpo debería esperar, qué response debería devolver, etc.
En este caso, podrías querer documentar cómo esa API externa *debería* verse. Qué *path operation* debería tener, qué body debería esperar, qué response debería devolver, etc.
## Una aplicación con callbacks { #an-app-with-callbacks }
@@ -167,13 +167,13 @@ Observa cómo la URL del callback utilizada contiene la URL recibida como parám
En este punto tienes las *path operation(s)* del callback necesarias (las que el *desarrollador externo* debería implementar en la *API externa*) en el router de callback que creaste arriba.
Ahora usa el parámetro `callbacks` en el *decorador de path operation de tu API* para pasar el atributo `.routes` (que en realidad es solo un `list` de rutas/*path operations*) de ese router de callback:
Ahora usa el parámetro `callbacks` en el *decorador de path operation de tu API* para pasar el atributo `.routes` de ese router de callback:
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
/// tip | Consejo
Observa que no estás pasando el router en sí (`invoices_callback_router`) a `callback=`, sino el atributo `.routes`, como en `invoices_callback_router.routes`.
Observa que no estás pasando el router en sí (`invoices_callback_router`) a `callbacks=`, sino su `.routes`, como en `invoices_callback_router.routes`. FastAPI usará esas rutas para generar la documentación OpenAPI del callback.
///
+2 -2
View File
@@ -22,7 +22,7 @@ Con **FastAPI**, usando OpenAPI, puedes definir los nombres de estos webhooks, l
Esto puede hacer mucho más fácil para tus usuarios **implementar sus APIs** para recibir tus requests de **webhook**, incluso podrían ser capaces de autogenerar algo de su propio código de API.
/// info | Información
/// note | Nota
Los webhooks están disponibles en OpenAPI 3.1.0 y superiores, soportados por FastAPI `0.99.0` y superiores.
@@ -36,7 +36,7 @@ Cuando creas una aplicación de **FastAPI**, hay un atributo `webhooks` que pued
Los webhooks que defines terminarán en el esquema de **OpenAPI** y en la interfaz automática de **documentación**.
/// info | Información
/// note | Nota
El objeto `app.webhooks` es en realidad solo un `APIRouter`, el mismo tipo que usarías al estructurar tu aplicación con múltiples archivos.
@@ -16,17 +16,11 @@ Tendrías que asegurarte de que sea único para cada operación.
### Usar el nombre de la *path operation function* como el operationId { #using-the-path-operation-function-name-as-the-operationid }
Si quieres usar los nombres de las funciones de tus APIs como `operationId`s, puedes iterar sobre todas ellas y sobrescribir el `operation_id` de cada *path operation* usando su `APIRoute.name`.
Si quieres usar los nombres de las funciones de tus APIs como `operationId`s, puedes pasar una `generate_unique_id_function` personalizada a `FastAPI`.
Deberías hacerlo después de agregar todas tus *path operations*.
La función recibe cada `APIRoute` y devuelve el `operationId` a usar para esa *path operation*.
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *}
/// tip | Consejo
Si llamas manualmente a `app.openapi()`, deberías actualizar los `operationId`s antes de eso.
///
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *}
/// warning | Advertencia
@@ -2,7 +2,7 @@
Probablemente leíste antes que puedes establecer un [Código de Estado de Response](../tutorial/response-status-code.md) por defecto.
Pero en algunos casos necesitas devolver un código de estado diferente al predeterminado.
Pero en algunos casos necesitas devolver un código de estado diferente al por defecto.
## Caso de uso { #use-case }
+3 -3
View File
@@ -1,6 +1,6 @@
# Cookies de Response { #response-cookies }
## Usar un parámetro `Response` { #use-a-response-parameter }
## Usa un parámetro `Response` { #use-a-response-parameter }
Puedes declarar un parámetro de tipo `Response` en tu *path operation function*.
@@ -16,11 +16,11 @@ Y si declaraste un `response_model`, todavía se utilizará para filtrar y conve
También puedes declarar el parámetro `Response` en las dependencias, y establecer cookies (y headers) en ellas.
## Devolver una `Response` directamente { #return-a-response-directly }
## Devuelve una `Response` directamente { #return-a-response-directly }
También puedes crear cookies al devolver una `Response` directamente en tu código.
Para hacer eso, puedes crear un response como se describe en [Devolver un Response Directamente](response-directly.md).
Para hacer eso, puedes crear un response como se describe en [Devuelve un Response Directamente](response-directly.md).
Luego establece Cookies en ella, y luego devuélvela:
+3 -3
View File
@@ -16,9 +16,9 @@ Normalmente tendrás mucho mejor rendimiento usando un [Response Model](../tutor
## Devolver una `Response` { #return-a-response }
De hecho, puedes devolver cualquier `Response` o cualquier subclase de ella.
Puedes devolver una `Response` o cualquier subclase de ella.
/// info | Información
/// note | Nota
`JSONResponse` en sí misma es una subclase de `Response`.
@@ -78,6 +78,6 @@ En su lugar, toma los bytes JSON generados con Pydantic usando el response model
Cuando devuelves una `Response` directamente, sus datos no son validados, convertidos (serializados), ni documentados automáticamente.
Pero aún puedes documentarlo como se describe en [Additional Responses in OpenAPI](additional-responses.md).
Pero aún puedes documentarlo como se describe en [Respuestas adicionales en OpenAPI](additional-responses.md).
Puedes ver en secciones posteriores cómo usar/declarar estas `Response`s personalizadas mientras todavía tienes conversión automática de datos, documentación, etc.
@@ -1,5 +1,6 @@
# Headers de Response { #response-headers }
## Usa un parámetro `Response` { #use-a-response-parameter }
Puedes declarar un parámetro de tipo `Response` en tu *path operation function* (como puedes hacer para cookies).
@@ -1,5 +1,6 @@
# Scopes de OAuth2 { #oauth2-scopes }
Puedes usar scopes de OAuth2 directamente con **FastAPI**, están integrados para funcionar de manera fluida.
Esto te permitiría tener un sistema de permisos más detallado, siguiendo el estándar de OAuth2, integrado en tu aplicación OpenAPI (y la documentación de la API).
@@ -46,7 +47,7 @@ Normalmente se utilizan para declarar permisos de seguridad específicos, por ej
* `instagram_basic` es usado por Facebook / Instagram.
* `https://www.googleapis.com/auth/drive` es usado por Google.
/// info | Información
/// note | Nota
En OAuth2 un "scope" es solo un string que declara un permiso específico requerido.
@@ -126,7 +127,7 @@ Lo estamos haciendo aquí para demostrar cómo **FastAPI** maneja scopes declara
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
/// info | Información Técnica
/// note | Detalles técnicos
`Security` es en realidad una subclase de `Depends`, y tiene solo un parámetro extra que veremos más adelante.
+11 -11
View File
@@ -20,7 +20,7 @@ Eso significa que cualquier valor leído en Python desde una variable de entorno
## Pydantic `Settings` { #pydantic-settings }
Afortunadamente, Pydantic proporciona una gran utilidad para manejar estas configuraciones provenientes de variables de entorno con [Pydantic: Settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/).
Afortunadamente, Pydantic proporciona una gran utilidad para manejar estas configuraciones provenientes de variables de entorno con [Pydantic: Gestión de Settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/).
### Instalar `pydantic-settings` { #install-pydantic-settings }
@@ -120,7 +120,7 @@ También necesitarías un archivo `__init__.py` como viste en [Aplicaciones Más
En algunas ocasiones podría ser útil proporcionar las configuraciones desde una dependencia, en lugar de tener un objeto global con `settings` que se use en todas partes.
Esto podría ser especialmente útil durante las pruebas, ya que es muy fácil sobrescribir una dependencia con tus propias configuraciones personalizadas.
Esto podría ser especialmente útil al escribir pruebas, ya que es muy fácil sobrescribir una dependencia con tus propias configuraciones personalizadas.
### El archivo de configuración { #the-config-file }
@@ -148,9 +148,9 @@ Y luego podemos requerirlo desde la *path operation function* como una dependenc
{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *}
### Configuraciones y pruebas { #settings-and-testing }
### Configuraciones y escribir pruebas { #settings-and-testing }
Luego sería muy fácil proporcionar un objeto de configuraciones diferente durante las pruebas al crear una sobrescritura de dependencia para `get_settings`:
Luego sería muy fácil proporcionar un objeto de configuraciones diferente al escribir pruebas creando una sobrescritura de dependencia para `get_settings`:
{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *}
@@ -160,7 +160,7 @@ Luego podemos probar que se está usando.
## Leer un archivo `.env` { #reading-a-env-file }
Si tienes muchas configuraciones que posiblemente cambien mucho, tal vez en diferentes entornos, podría ser útil ponerlos en un archivo y luego leerlos desde allí como si fueran variables de entorno.
Si tienes muchas configuraciones que posiblemente cambien mucho, tal vez en diferentes entornos, podría ser útil ponerlas en un archivo y luego leerlas desde allí como si fueran variables de entorno.
Esta práctica es lo suficientemente común que tiene un nombre, estas variables de entorno generalmente se colocan en un archivo `.env`, y el archivo se llama un "dotenv".
@@ -172,7 +172,7 @@ Pero un archivo dotenv realmente no tiene que tener ese nombre exacto.
///
Pydantic tiene soporte para leer desde estos tipos de archivos usando un paquete externo. Puedes leer más en [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support).
Pydantic tiene soporte para leer desde estos tipos de archivos usando un paquete externo. Puedes leer más en [Pydantic Settings: soporte para Dotenv (.env)](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support).
/// tip | Consejo
@@ -197,7 +197,7 @@ Y luego actualizar tu `config.py` con:
/// tip | Consejo
El atributo `model_config` se usa solo para configuración de Pydantic. Puedes leer más en [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/).
El atributo `model_config` se usa solo para configuración de Pydantic. Puedes leer más en [Pydantic: Conceptos: Configuración](https://docs.pydantic.dev/latest/concepts/config/).
///
@@ -289,14 +289,14 @@ participant execute as Ejecutar función
En el caso de nuestra dependencia `get_settings()`, la función ni siquiera toma argumentos, por lo que siempre devuelve el mismo valor.
De esa manera, se comporta casi como si fuera solo una variable global. Pero como usa una función de dependencia, entonces podemos sobrescribirla fácilmente para las pruebas.
De esa manera, se comporta casi como si fuera solo una variable global. Pero como usa una función de dependencia, entonces podemos sobrescribirla fácilmente al escribir pruebas.
`@lru_cache` es parte de `functools`, que es parte del paquete estándar de Python, puedes leer más sobre él en las [docs de Python para `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache).
`@lru_cache` es parte de `functools`, que es parte del paquete estándar de Python, puedes leer más sobre él en la [documentación de Python para `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache).
## Resumen { #recap }
Puedes usar Pydantic Settings para manejar las configuraciones o ajustes de tu aplicación, con todo el poder de los modelos de Pydantic.
* Al usar una dependencia, puedes simplificar las pruebas.
* Al usar una dependencia, puedes simplificar la escritura de pruebas.
* Puedes usar archivos `.env` con él.
* Usar `@lru_cache` te permite evitar leer el archivo dotenv una y otra vez para cada request, mientras te permite sobrescribirlo durante las pruebas.
* Usar `@lru_cache` te permite evitar leer el archivo dotenv una y otra vez para cada request, mientras te permite sobrescribirlo al escribir pruebas.
+7 -7
View File
@@ -2,9 +2,9 @@
Si quieres transmitir datos que se puedan estructurar como JSON, deberías [Transmitir JSON Lines](../tutorial/stream-json-lines.md).
Pero si quieres transmitir datos binarios puros o strings, aquí tienes cómo hacerlo.
Pero si quieres **transmitir datos binarios puros** o strings, aquí tienes cómo hacerlo.
/// info | Información
/// note | Nota
Añadido en FastAPI 0.134.0.
@@ -12,11 +12,11 @@ Añadido en FastAPI 0.134.0.
## Casos de uso { #use-cases }
Podrías usar esto si quieres transmitir strings puros, por ejemplo directamente de la salida de un servicio de AI LLM.
Podrías usar esto si quieres transmitir strings puros, por ejemplo directamente de la salida de un servicio de **AI LLM**.
También podrías usarlo para transmitir archivos binarios grandes, donde transmites cada bloque de datos a medida que lo lees, sin tener que leerlo todo en memoria de una sola vez.
También podrías usarlo para transmitir **archivos binarios grandes**, donde transmites cada bloque de datos a medida que lo lees, sin tener que leerlo todo en memoria de una sola vez.
También podrías transmitir video o audio de esta manera; incluso podría generarse mientras lo procesas y lo envías.
También podrías transmitir **video** o **audio** de esta manera; incluso podría generarse mientras lo procesas y lo envías.
## Un `StreamingResponse` con `yield` { #a-streamingresponse-with-yield }
@@ -40,7 +40,7 @@ Como FastAPI no intentará convertir los datos a JSON con Pydantic ni serializar
{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *}
Esto también significa que con `StreamingResponse` tienes la libertad y la responsabilidad de producir y codificar los bytes de datos exactamente como necesites enviarlos, independientemente de las anotaciones de tipos. 🤓
Esto también significa que con `StreamingResponse` tienes la **libertad** y la **responsabilidad** de producir y codificar los bytes de datos exactamente como necesites enviarlos, independientemente de las anotaciones de tipos. 🤓
### Transmitir bytes { #stream-bytes }
@@ -90,7 +90,7 @@ Por ejemplo, no tienen un `await file.read()`, ni un `async for chunk in file`.
Y en muchos casos leerlos sería una operación bloqueante (que podría bloquear el event loop), porque se leen desde disco o desde la red.
/// info | Información
/// note | Nota
El ejemplo anterior es en realidad una excepción, porque el objeto `io.BytesIO` ya está en memoria, así que leerlo no bloqueará nada.
+4 -4
View File
@@ -40,7 +40,7 @@ Ten en cuenta que ambos tienen el mismo host.
Luego, usando el frontend, puedes hacer que el agente de IA haga cosas en tu nombre.
Como está corriendo localmente y no en Internet abierta, decides no tener ninguna autenticación configurada, confiando simplemente en el acceso a la red local.
Como está corriendo **localmente** y no en Internet abierta, decides **no tener ninguna autenticación** configurada, confiando simplemente en el acceso a la red local.
Entonces, uno de tus usuarios podría instalarlo y ejecutarlo localmente.
@@ -69,9 +69,9 @@ Si tu app está en Internet abierta, no “confiarías en la red” ni permitir
Los atacantes podrían simplemente ejecutar un script para enviar requests a tu API, sin necesidad de interacción del navegador, así que probablemente ya estás asegurando cualquier endpoint privilegiado.
En ese caso, este ataque/riesgo no aplica a ti.
En ese caso, **este ataque/riesgo no aplica a ti**.
Este riesgo y ataque es relevante principalmente cuando la app corre en la red local y esa es la única protección asumida.
Este riesgo y ataque es relevante principalmente cuando la app corre en la **red local** y esa es la **única protección asumida**.
## Permitir requests sin Content-Type { #allowing-requests-without-content-type }
@@ -81,7 +81,7 @@ Si necesitas soportar clientes que no envían un header `Content-Type`, puedes d
Con esta configuración, las requests sin un header `Content-Type` tendrán su body parseado como JSON, que es el mismo comportamiento de versiones anteriores de FastAPI.
/// info | Información
/// note | Nota
Este comportamiento y configuración se añadieron en FastAPI 0.132.0.
+1 -1
View File
@@ -111,7 +111,7 @@ Funcionan de la misma manera que para otros endpoints de FastAPI/*path operation
{* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *}
/// info | Información
/// note | Nota
Como esto es un WebSocket no tiene mucho sentido lanzar un `HTTPException`, en su lugar lanzamos un `WebSocketException`.
+2 -1
View File
@@ -1,12 +1,13 @@
# Incluyendo WSGI - Flask, Django, otros { #including-wsgi-flask-django-others }
Puedes montar aplicaciones WSGI como viste con [Sub Aplicaciones - Mounts](sub-applications.md), [Detrás de un Proxy](behind-a-proxy.md).
Para eso, puedes usar el `WSGIMiddleware` y usarlo para envolver tu aplicación WSGI, por ejemplo, Flask, Django, etc.
## Usando `WSGIMiddleware` { #using-wsgimiddleware }
/// info | Información
/// note | Nota
Esto requiere instalar `a2wsgi`, por ejemplo con `pip install a2wsgi`.
+8 -8
View File
@@ -24,7 +24,7 @@ Fue creado para generar el HTML en el backend, no para crear APIs utilizadas por
### [Django REST Framework](https://www.django-rest-framework.org/) { #django-rest-framework }
El framework Django REST fue creado para ser un kit de herramientas flexible para construir APIs Web utilizando Django, mejorando sus capacidades API.
Django REST Framework fue creado para ser un toolkit flexible para construir APIs Web usando Django por debajo, para mejorar sus capacidades de API.
Es utilizado por muchas empresas, incluidas Mozilla, Red Hat y Eventbrite.
@@ -88,7 +88,7 @@ La forma en que lo usas es muy sencilla. Por ejemplo, para hacer un `GET` reques
response = requests.get("http://example.com/some/url")
```
La operación de path equivalente en FastAPI podría verse como:
La *path operation* API equivalente de FastAPI podría verse como:
```Python hl_lines="1"
@app.get("/some/url")
@@ -183,7 +183,7 @@ Pero la documentación todavía falta. Entonces APISpec fue creado.
Es un plug-in para muchos frameworks (y hay un plug-in para Starlette también).
La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja un path.
La manera en que funciona es que escribes la definición del esquema usando el formato YAML dentro del docstring de cada función que maneja una ruta.
Y genera esquemas OpenAPI.
@@ -245,11 +245,11 @@ Logra algo algo similar a lo que se puede hacer con Flask-apispec.
Tiene un sistema de inyección de dependencias integrado, inspirado por Angular 2. Requiere pre-registrar los "inyectables" (como todos los otros sistemas de inyección de dependencias que conozco), por lo que añade a la verbosidad y repetición de código.
Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte editorial es bastante bueno.
Como los parámetros se describen con tipos de TypeScript (similar a las anotaciones de tipos en Python), el soporte del editor es bastante bueno.
Pero como los datos de TypeScript no se preservan después de la compilación a JavaScript, no puede depender de los tipos para definir validación, serialización y documentación al mismo tiempo. Debido a esto y algunas decisiones de diseño, para obtener validación, serialización y generación automática del esquema, es necesario agregar decoradores en muchos lugares. Por lo tanto, se vuelve bastante verboso.
No puede manejar muy bien modelos anidados. Entonces, si el cuerpo JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente.
No puede manejar muy bien modelos anidados. Entonces, si el body JSON en la request es un objeto JSON que tiene campos internos que a su vez son objetos JSON anidados, no puede ser documentado y validado apropiadamente.
/// tip | Inspiró a **FastAPI** a
@@ -311,11 +311,11 @@ Requiere configuraciones un poquito más verbosas. Y dado que se basa en WSGI (e
El sistema de inyección de dependencias requiere pre-registrar las dependencias y las dependencias se resuelven en base a los tipos declarados. Por lo tanto, no es posible declarar más de un "componente" que proporcione cierto tipo.
Los paths se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas.
Las rutas se declaran en un solo lugar, usando funciones declaradas en otros lugares (en lugar de usar decoradores que pueden colocarse justo encima de la función que maneja el endpoint). Esto se acerca más a cómo lo hace Django que a cómo lo hace Flask (y Starlette). Separa en el código cosas que están relativamente acopladas.
/// tip | Inspiró a **FastAPI** a
Definir validaciones extra para tipos de datos usando el valor "default" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes.
Definir validaciones extra para tipos de datos usando el valor "por defecto" de los atributos del modelo. Esto mejora el soporte del editor y no estaba disponible en Pydantic antes.
Esto en realidad inspiró la actualización de partes de Pydantic, para soportar el mismo estilo de declaración de validación (toda esta funcionalidad ya está disponible en Pydantic).
@@ -433,7 +433,7 @@ Tiene:
* CORS, GZip, Archivos estáticos, Responses en streaming.
* Soporte para sesiones y cookies.
* Cobertura de tests del 100%.
* code base 100% tipada.
* codebase 100% con anotaciones de tipos.
* Pocas dependencias obligatorias.
Starlette es actualmente el framework de Python más rápido probado. Solo superado por Uvicorn, que no es un framework, sino un servidor.
+4 -4
View File
@@ -89,7 +89,7 @@ Como el tiempo de ejecución se consume principalmente esperando operaciones de
Se llama "asíncrono" porque la computadora / programa no tiene que estar "sincronizado" con la tarea lenta, esperando el momento exacto en que la tarea termine, sin hacer nada, para poder tomar el resultado de la tarea y continuar el trabajo.
En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poco en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos.
En lugar de eso, al ser un sistema "asíncrono", una vez terminado, la tarea puede esperar un poquito en la cola (algunos microsegundos) para que la computadora / programa termine lo que salió a hacer, y luego regrese para tomar los resultados y continuar trabajando con ellos.
Para el "sincrónico" (contrario al "asíncrono") comúnmente también usan el término "secuencial", porque la computadora / programa sigue todos los pasos en secuencia antes de cambiar a una tarea diferente, incluso si esos pasos implican esperar.
@@ -151,7 +151,7 @@ Imagina que eres la computadora / programa 🤖 en esa historia.
Mientras estás en la fila, estás inactivo 😴, esperando tu turno, sin hacer nada muy "productivo". Pero la fila es rápida porque el cajero solo está tomando los pedidos (no preparándolos), así que está bien.
Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, verificas que das el billete o tarjeta correctos, verificas que te cobren correctamente, verificas que el pedido tenga los artículos correctos, etc.
Luego, cuando es tu turno, haces un trabajo realmente "productivo", procesas el menú, decides lo que quieres, obtienes la elección de tu crush, pagas, revisas que das el billete o tarjeta correctos, revisas que te cobren correctamente, revisas que el pedido tenga los artículos correctos, etc.
Pero luego, aunque todavía no tienes tus hamburguesas, tu trabajo con el cajero está "en pausa" ⏸, porque tienes que esperar 🕙 a que tus hamburguesas estén listas.
@@ -387,7 +387,7 @@ En versiones previas de NodeJS / JavaScript en el Navegador, habrías usado "cal
## Coroutines { #coroutines }
**Coroutines** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él.
**Coroutine** es simplemente el término muy elegante para la cosa que devuelve una función `async def`. Python sabe que es algo parecido a una función, que puede comenzar y que terminará en algún momento, pero que podría pausar ⏸ internamente también, siempre que haya un `await` dentro de él.
Pero toda esta funcionalidad de usar código asíncrono con `async` y `await` a menudo se resume como utilizar "coroutines". Es comparable a la funcionalidad clave principal de Go, las "Goroutines".
@@ -417,7 +417,7 @@ Si tienes bastante conocimiento técnico (coroutines, hilos, bloqueo, etc.) y ti
Cuando declaras una *path operation function* con `def` normal en lugar de `async def`, se ejecuta en un threadpool externo que luego es esperado, en lugar de ser llamado directamente (ya que bloquearía el servidor).
Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir funciones de *path operation* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice <abbr title="Input/Output - Entrada/Salida: lectura o escritura en disco, comunicaciones de red.">I/O</abbr> de bloqueo.
Si vienes de otro framework async que no funciona de la manera descrita anteriormente y estás acostumbrado a definir *path operation functions* solo de cómputo trivial con `def` normal para una pequeña ganancia de rendimiento (alrededor de 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen código que realice <abbr title="Input/Output - Entrada/Salida: lectura o escritura en disco, comunicaciones de red.">I/O</abbr> de bloqueo.
Aun así, en ambas situaciones, es probable que **FastAPI** [siga siendo más rápida](index.md#performance) que (o al menos comparable a) tu framework anterior.
+1 -1
View File
@@ -16,7 +16,7 @@ FastAPI Cloud es el sponsor principal y proveedor de financiamiento de los proye
## Proveedores de Nube - Sponsors { #cloud-providers-sponsors }
Otros proveedores de nube ✨ [**son sponsors de FastAPI**](../help-fastapi.md#sponsor-the-author) ✨ también. 🙇
Algunos otros proveedores de nube ✨ [**son sponsors de FastAPI**](https://github.com/sponsors/tiangolo) ✨ también. 🙇
También podrías considerarlos para seguir sus guías y probar sus servicios:
+1
View File
@@ -1,5 +1,6 @@
# Conceptos de Implementación { #deployments-concepts }
Cuando implementas una aplicación **FastAPI**, o en realidad, cualquier tipo de API web, hay varios conceptos que probablemente te importen, y al entenderlos, puedes encontrar la **forma más adecuada** de **implementar tu aplicación**.
Algunos de los conceptos importantes son:
+3 -2
View File
@@ -1,5 +1,6 @@
# FastAPI en Contenedores - Docker { #fastapi-in-containers-docker }
Al desplegar aplicaciones de FastAPI, un enfoque común es construir una **imagen de contenedor de Linux**. Normalmente se realiza usando [**Docker**](https://www.docker.com/). Luego puedes desplegar esa imagen de contenedor de varias formas.
Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **replicabilidad**, **simplicidad**, y otras.
@@ -132,7 +133,7 @@ Successfully installed fastapi pydantic
</div>
/// info | Información
/// note | Nota
Existen otros formatos y herramientas para definir e instalar dependencias de paquetes.
@@ -556,7 +557,7 @@ Si estás usando contenedores (por ejemplo, Docker, Kubernetes), entonces hay do
Si tienes **múltiples contenedores**, probablemente cada uno ejecutando un **proceso único** (por ejemplo, en un cluster de **Kubernetes**), entonces probablemente querrías tener un **contenedor separado** realizando el trabajo de los **pasos previos** en un solo contenedor, ejecutando un solo proceso, **antes** de ejecutar los contenedores worker replicados.
/// info | Información
/// note | Nota
Si estás usando Kubernetes, probablemente sería un [Contenedor de Inicialización](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/).
+3 -21
View File
@@ -1,26 +1,6 @@
# FastAPI Cloud { #fastapi-cloud }
Puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con **un solo comando**; ve y únete a la lista de espera si aún no lo has hecho. 🚀
## Iniciar sesión { #login }
Asegúrate de que ya tienes una cuenta de **FastAPI Cloud** (te invitamos desde la lista de espera 😉).
Luego inicia sesión:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
## Desplegar { #deploy }
Ahora despliega tu app, con **un solo comando**:
Puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con **un solo comando**. 🚀
<div class="termy">
@@ -36,6 +16,8 @@ Deploying to FastAPI Cloud...
</div>
La CLI detectará automáticamente tu aplicación de FastAPI y la desplegará en la nube. Si no has iniciado sesión, se abrirá tu navegador para completar el proceso de autenticación.
¡Eso es todo! Ahora puedes acceder a tu app en esa URL. ✨
## Acerca de FastAPI Cloud { #about-fastapi-cloud }
+1 -1
View File
@@ -32,7 +32,7 @@ Ahora, desde una **perspectiva de desarrollador**, aquí hay varias cosas a tene
* Esta extensión SNI permite que un solo servidor (con una **sola dirección IP**) tenga **varios certificados HTTPS** y sirva **múltiples dominios/aplicaciones HTTPS**.
* Para que esto funcione, un componente (programa) **único** que se ejecute en el servidor, escuchando en la **dirección IP pública**, debe tener **todos los certificados HTTPS** en el servidor.
* **Después** de obtener una conexión segura, el protocolo de comunicación sigue siendo **HTTP**.
* Los contenidos están **encriptados**, aunque se envn con el **protocolo HTTP**.
* Los contenidos están **encriptados**, aunque se envíen con el **protocolo HTTP**.
Es una práctica común tener **un programa/servidor HTTP** ejecutándose en el servidor (la máquina, host, etc.) y **gestionando todas las partes de HTTPS**: recibiendo los **requests HTTPS encriptados**, enviando los **requests HTTP desencriptados** a la aplicación HTTP real que se ejecuta en el mismo servidor (la aplicación **FastAPI**, en este caso), tomando el **response HTTP** de la aplicación, **encriptándolo** usando el **certificado HTTPS** adecuado y enviándolo de vuelta al cliente usando **HTTPS**. Este servidor a menudo se llama un **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)**.
+1 -2
View File
@@ -56,7 +56,6 @@ Hay varias alternativas, incluyendo:
* [Hypercorn](https://hypercorn.readthedocs.io/): un servidor ASGI compatible con HTTP/2 y Trio entre otras funcionalidades.
* [Daphne](https://github.com/django/daphne): el servidor ASGI construido para Django Channels.
* [Granian](https://github.com/emmett-framework/granian): Un servidor HTTP Rust para aplicaciones en Python.
* [NGINX Unit](https://unit.nginx.org/howto/fastapi/): NGINX Unit es un runtime para aplicaciones web ligero y versátil.
## Máquina Servidor y Programa Servidor { #server-machine-and-server-program }
@@ -94,7 +93,7 @@ Un proceso similar se aplicaría a cualquier otro programa de servidor ASGI.
Al añadir `standard`, Uvicorn instalará y usará algunas dependencias adicionales recomendadas.
Eso incluye `uvloop`, el reemplazo de alto rendimiento para `asyncio`, que proporciona un gran impulso de rendimiento en concurrencia.
Eso incluye `uvloop`, el reemplazo directo de alto rendimiento para `asyncio`, que proporciona un gran impulso de rendimiento en concurrencia.
Cuando instalas FastAPI con algo como `pip install "fastapi[standard]"` ya obtienes `uvicorn[standard]` también.
+1 -1
View File
@@ -17,7 +17,7 @@ Como viste en el capítulo anterior sobre [Conceptos de Despliegue](concepts.md)
Aquí te mostraré cómo usar **Uvicorn** con **worker processes** usando el comando `fastapi` o el comando `uvicorn` directamente.
/// info | Información
/// note | Nota
Si estás usando contenedores, por ejemplo con Docker o Kubernetes, te contaré más sobre eso en el próximo capítulo: [FastAPI en Contenedores - Docker](docker.md).
+1 -1
View File
@@ -10,7 +10,7 @@ La **Extensión de FastAPI** está disponible tanto para [VS Code](https://code.
### Descubrimiento de la aplicación { #application-discovery }
Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que creen un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`).
Por defecto, la extensión descubrirá automáticamente aplicaciones FastAPI en tu espacio de trabajo escaneando archivos que crean un instance de `FastAPI()`. Si la detección automática no funciona con la estructura de tu proyecto, puedes especificar un punto de entrada mediante `[tool.fastapi]` en `pyproject.toml` o la configuración de VS Code `fastapi.entryPoint` usando notación de módulo (p. ej. `myapp.main:app`).
## Funcionalidades { #features }
+1
View File
@@ -1,5 +1,6 @@
# Variables de Entorno { #environment-variables }
/// tip | Consejo
Si ya sabes qué son las "variables de entorno" y cómo usarlas, siéntete libre de saltarte esto.
+2 -2
View File
@@ -130,7 +130,7 @@ Todos los esquemas de seguridad definidos en OpenAPI, incluyendo:
* Parámetros de query.
* Cookies, etc.
Además de todas las características de seguridad de Starlette (incluyendo **cookies de sesión**).
Además de todas las funcionalidades de seguridad de Starlette (incluyendo **cookies de sesión**).
Todo construido como herramientas y componentes reutilizables que son fáciles de integrar con tus sistemas, almacenes de datos, bases de datos relacionales y NoSQL, etc.
@@ -179,7 +179,7 @@ Con **FastAPI** obtienes todas las funcionalidades de **Starlette** (ya que Fast
**FastAPI** es totalmente compatible con (y está basado en) [**Pydantic**](https://docs.pydantic.dev/). Por lo tanto, cualquier código adicional de Pydantic que tengas, también funcionará.
Incluyendo paquetes externos también basados en Pydantic, como <abbr title="Object-Relational Mapper - Mapeador Objeto-Relacional">ORM</abbr>s, <abbr title="Object-Document Mapper - Mapeador Objeto-Documento">ODM</abbr>s para bases de datos.
Incluyendo paquetes externos también basados en Pydantic, como <abbr title="Object-Relational Mapper - Mapeador Objeto-Relacional">ORM</abbr>s y <abbr title="Object-Document Mapper - Mapeador Objeto-Documento">ODM</abbr>s para bases de datos.
Esto también significa que, en muchos casos, puedes pasar el mismo objeto que obtienes de un request **directamente a la base de datos**, ya que todo se valida automáticamente.
+1 -1
View File
@@ -68,7 +68,7 @@ Puedes [crear una nueva pregunta](https://github.com/fastapi/fastapi/discussions
## Únete al chat { #join-the-chat }
Únete al servidor de chat 👥 [Discord](https://discord.gg/VQjSZaeJmf) 👥 y charla con otros en la comunidad de FastAPI.
Únete al 👥 [servidor de chat de Discord](https://discord.gg/VQjSZaeJmf) 👥 y charla con otros en la comunidad de FastAPI.
/// tip | Consejo
+4 -4
View File
@@ -1,4 +1,4 @@
# Configurar Swagger UI { #configure-swagger-ui }
# Configura Swagger UI { #configure-swagger-ui }
Puedes configurar algunos [parámetros adicionales de Swagger UI](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/).
@@ -8,7 +8,7 @@ Para configurarlos, pasa el argumento `swagger_ui_parameters` al crear el objeto
FastAPI convierte las configuraciones a **JSON** para hacerlas compatibles con JavaScript, ya que eso es lo que Swagger UI necesita.
## Desactivar el resaltado de sintaxis { #disable-syntax-highlighting }
## Desactiva el resaltado de sintaxis { #disable-syntax-highlighting }
Por ejemplo, podrías desactivar el resaltado de sintaxis en Swagger UI.
@@ -24,7 +24,7 @@ Pero puedes desactivarlo estableciendo `syntaxHighlight` en `False`:
<img src="/img/tutorial/extending-openapi/image03.png">
## Cambiar el tema { #change-the-theme }
## Cambia el tema { #change-the-theme }
De la misma manera, podrías configurar el tema del resaltado de sintaxis con la clave `"syntaxHighlight.theme"` (ten en cuenta que tiene un punto en el medio):
@@ -34,7 +34,7 @@ Esa configuración cambiaría el tema de color del resaltado de sintaxis:
<img src="/img/tutorial/extending-openapi/image04.png">
## Cambiar los parámetros por defecto de Swagger UI { #change-default-swagger-ui-parameters }
## Cambia los parámetros por defecto de Swagger UI { #change-default-swagger-ui-parameters }
FastAPI incluye algunos parámetros de configuración por defecto apropiados para la mayoría de los casos de uso.
@@ -18,8 +18,8 @@ Si apenas estás comenzando con **FastAPI**, quizás quieras saltar esta secció
Algunos casos de uso incluyen:
* Convertir cuerpos de requests no-JSON a JSON (por ejemplo, [`msgpack`](https://msgpack.org/index.html)).
* Descomprimir cuerpos de requests comprimidos con gzip.
* Convertir request bodies no-JSON a JSON (por ejemplo, [`msgpack`](https://msgpack.org/index.html)).
* Descomprimir request bodies comprimidos con gzip.
* Registrar automáticamente todos los request bodies.
## Manejo de codificaciones personalizadas de request body { #handling-custom-request-body-encodings }
@@ -32,7 +32,7 @@ Y una subclase de `APIRoute` para usar esa clase de request personalizada.
/// tip | Consejo
Este es un ejemplo sencillo para demostrar cómo funciona. Si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) proporcionado.
Este es un ejemplo de juguete para demostrar cómo funciona, si necesitas soporte para Gzip, puedes usar el [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) proporcionado.
///
@@ -60,11 +60,11 @@ Aquí lo usamos para crear un `GzipRequest` a partir del request original.
Un `Request` tiene un atributo `request.scope`, que es simplemente un `dict` de Python que contiene los metadatos relacionados con el request.
Un `Request` también tiene un `request.receive`, que es una función para "recibir" el request body.
Un `Request` también tiene un `request.receive`, que es una función para "recibir" el body del request.
El `dict` `scope` y la función `receive` son ambos parte de la especificación ASGI.
Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva *Request instance*.
Y esas dos cosas, `scope` y `receive`, son lo que se necesita para crear una nueva instance de `Request`.
Para aprender más sobre el `Request`, revisa [la documentación de Starlette sobre Requests](https://www.starlette.dev/requests/).
@@ -94,7 +94,7 @@ Todo lo que necesitamos hacer es manejar el request dentro de un bloque `try`/`e
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *}
Si ocurre una excepción, la `Request instance` aún estará en el alcance, así que podemos leer y hacer uso del request body cuando manejamos el error:
Si ocurre una excepción, el instance de `Request` todavía estará en el alcance, así que podemos leer y hacer uso del request body cuando manejamos el error:
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *}
+10 -2
View File
@@ -25,9 +25,17 @@ Y esa función `get_openapi()` recibe como parámetros:
* `openapi_version`: La versión de la especificación OpenAPI utilizada. Por defecto, la más reciente: `3.1.0`.
* `summary`: Un breve resumen de la API.
* `description`: La descripción de tu API, esta puede incluir markdown y se mostrará en la documentación.
* `routes`: Una list de rutas, estas son cada una de las *path operations* registradas. Se toman de `app.routes`.
* `routes`: Las rutas de la aplicación, tomadas de `app.routes`. FastAPI las usa para recolectar las *path operations* registradas, incluidas las de los routers incluidos.
/// info | Información
/// tip | Detalles técnicos
`app.routes` es un árbol de rutas de nivel inferior. Puede incluir rutas candidatas que FastAPI usa internamente para routers incluidos, no solo objetos `APIRoute` finales.
Aun así puedes pasar `app.routes` a `get_openapi()`. FastAPI recorrerá ese árbol de rutas para recolectar las path operations efectivas.
///
/// note | Nota
El parámetro `summary` está disponible en OpenAPI 3.1.0 y versiones superiores, soportado por FastAPI 0.99.0 y superiores.
+1 -1
View File
@@ -29,7 +29,7 @@ Aquí algunos de los paquetes de **GraphQL** que tienen soporte **ASGI**. Podrí
## GraphQL con Strawberry { #graphql-with-strawberry }
Si necesitas o quieres trabajar con **GraphQL**, [**Strawberry**](https://strawberry.rocks/) es el paquete **recomendado** ya que tiene un diseño muy similar al diseño de **FastAPI**, todo basado en **anotaciones de tipos**.
Si necesitas o quieres trabajar con **GraphQL**, [**Strawberry**](https://strawberry.rocks/) es el paquete **recomendado** ya que tiene el diseño más cercano al diseño de **FastAPI**, todo basado en **anotaciones de tipos**.
Dependiendo de tu caso de uso, podrías preferir usar un paquete diferente, pero si me preguntas, probablemente te sugeriría probar **Strawberry**.
@@ -8,6 +8,8 @@ FastAPI versión 0.119.0 introdujo compatibilidad parcial con Pydantic v1 desde
FastAPI 0.126.0 eliminó la compatibilidad con Pydantic v1, aunque siguió soportando `pydantic.v1` por un poquito más de tiempo.
FastAPI 0.128.0 también eliminó la compatibilidad con `pydantic.v1`, así que las versiones más recientes de FastAPI requieren Pydantic v2.
/// warning | Advertencia
El equipo de Pydantic dejó de dar soporte a Pydantic v1 para las versiones más recientes de Python, comenzando con **Python 3.14**.
@@ -54,6 +56,16 @@ Esto significa que puedes instalar la versión más reciente de Pydantic v2 e im
### Compatibilidad de FastAPI con Pydantic v1 en v2 { #fastapi-support-for-pydantic-v1-in-v2 }
/// warning | Advertencia
Esta compatibilidad de FastAPI con modelos de `pydantic.v1` se añadió en **FastAPI 0.119.0** y se eliminó en **FastAPI 0.128.0**. Estaba pensada para ser una ayuda temporal para la migración a Pydantic v2.
En las versiones actuales de FastAPI, usar un modelo de `pydantic.v1` en tu app generará un error.
El resto de esta sección describe la compatibilidad temporal disponible solo en esas versiones antiguas.
///
Desde FastAPI 0.119.0, también hay compatibilidad parcial para Pydantic v1 desde dentro de Pydantic v2, para facilitar la migración a v2.
Así que podrías actualizar Pydantic a la última versión 2 y cambiar los imports para usar el submódulo `pydantic.v1`, y en muchos casos simplemente funcionaría.
@@ -122,6 +134,12 @@ Si necesitas usar algunas de las herramientas específicas de FastAPI para pará
### Migra por pasos { #migrate-in-steps }
/// warning | Advertencia
La migración gradual usando tanto modelos de Pydantic v1 como de v2 en la misma app descrita abajo solo funciona en **FastAPI 0.119.0 a 0.127.x**. Se eliminó en **FastAPI 0.128.0**, las versiones más recientes requieren modelos de **Pydantic v2**.
///
/// tip | Consejo
Primero prueba con `bump-pydantic`, si tus tests pasan y eso funciona, entonces terminaste con un solo comando. ✨
@@ -77,7 +77,7 @@ Pero para `Item-Output`, `description` **es requerido**, tiene un asterisco rojo
Con esta funcionalidad de **Pydantic v2**, la documentación de tu API es más **precisa**, y si tienes clientes y SDKs autogenerados, también serán más precisos, con una mejor **experiencia para desarrolladores** y consistencia. 🎉
## No Separar Esquemas { #do-not-separate-schemas }
## No separes esquemas { #do-not-separate-schemas }
Ahora, hay algunos casos donde podrías querer tener el **mismo esquema para entrada y salida**.
@@ -85,7 +85,7 @@ Probablemente el caso principal para esto es si ya tienes algún código cliente
En ese caso, puedes desactivar esta funcionalidad en **FastAPI**, con el parámetro `separate_input_output_schemas=False`.
/// info | Información
/// note | Nota
El soporte para `separate_input_output_schemas` fue agregado en FastAPI `0.102.0`. 🤓
+5 -5
View File
@@ -45,7 +45,7 @@ Las funcionalidades clave son:
* **Rápido**: Muy alto rendimiento, a la par con **NodeJS** y **Go** (gracias a Starlette y Pydantic). [Uno de los frameworks Python más rápidos disponibles](#performance).
* **Rápido de programar**: Aumenta la velocidad para desarrollar funcionalidades en aproximadamente un 200% a 300%. *
* **Menos bugs**: Reduce en aproximadamente un 40% los errores inducidos por humanos (desarrolladores). *
* **Intuitivo**: Gran soporte para editores. <dfn title="también conocido como: auto-complete, autocompletado, IntelliSense">Autocompletado</dfn> en todas partes. Menos tiempo depurando.
* **Intuitivo**: Gran soporte para editores. <dfn title="también conocido como autocompletado, autocompletado, IntelliSense">Autocompletado</dfn> en todas partes. Menos tiempo depurando.
* **Fácil**: Diseñado para ser fácil de usar y aprender. Menos tiempo leyendo documentación.
* **Corto**: Minimiza la duplicación de código. Múltiples funcionalidades desde cada declaración de parámetro. Menos bugs.
* **Robusto**: Obtén código listo para producción. Con documentación interactiva automática.
@@ -479,7 +479,7 @@ Para un ejemplo más completo incluyendo más funcionalidades, ve al <a href="ht
* Declaración de **parámetros** desde otros lugares diferentes como: **headers**, **cookies**, **campos de formulario** y **archivos**.
* Cómo establecer **restricciones de validación** como `maximum_length` o `regex`.
* Un sistema de **<dfn title="también conocido como: componentes, recursos, proveedores, servicios, inyectables">Inyección de Dependencias</dfn>** muy poderoso y fácil de usar.
* Un sistema de **<dfn title="también conocido como componentes, recursos, proveedores, servicios, inyectables">Inyección de Dependencias</dfn>** muy poderoso y fácil de usar.
* Seguridad y autenticación, incluyendo soporte para **OAuth2** con **tokens JWT** y autenticación **HTTP Basic**.
* Técnicas más avanzadas (pero igualmente fáciles) para declarar **modelos JSON profundamente anidados** (gracias a Pydantic).
* Integración con **GraphQL** usando [Strawberry](https://strawberry.rocks) y otros paquetes.
@@ -492,9 +492,7 @@ Para un ejemplo más completo incluyendo más funcionalidades, ve al <a href="ht
### Despliega tu app (opcional) { #deploy-your-app-optional }
Opcionalmente puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com), ve y únete a la lista de espera si no lo has hecho. 🚀
Si ya tienes una cuenta de **FastAPI Cloud** (te invitamos desde la lista de espera 😉), puedes desplegar tu aplicación con un solo comando.
Opcionalmente puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con un solo comando. 🚀
<div class="termy">
@@ -510,6 +508,8 @@ Deploying to FastAPI Cloud...
</div>
La CLI detectará automáticamente tu aplicación de FastAPI y la desplegará en la nube. Si no has iniciado sesión, se abrirá tu navegador para completar el proceso de autenticación.
¡Eso es todo! Ahora puedes acceder a tu app en esa URL. ✨
#### Acerca de FastAPI Cloud { #about-fastapi-cloud }
+9 -9
View File
@@ -9,18 +9,18 @@ Repositorio de GitHub: [Plantilla Full Stack FastAPI](https://github.com/tiangol
## Plantilla Full Stack FastAPI - Stack de tecnología y funcionalidades { #full-stack-fastapi-template-technology-stack-and-features }
- ⚡ [**FastAPI**](https://fastapi.tiangolo.com/es) para la API del backend en Python.
- 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para las interacciones con bases de datos SQL en Python (ORM).
- 🔍 [Pydantic](https://docs.pydantic.dev), utilizado por FastAPI, para la validación de datos y gestión de configuraciones.
- 💾 [PostgreSQL](https://www.postgresql.org) como base de datos SQL.
- 🧰 [SQLModel](https://sqlmodel.tiangolo.com) para las interacciones con bases de datos SQL en Python (ORM).
- 🔍 [Pydantic](https://docs.pydantic.dev), utilizado por FastAPI, para la validación de datos y gestión de configuraciones.
- 💾 [PostgreSQL](https://www.postgresql.org) como base de datos SQL.
- 🚀 [React](https://react.dev) para el frontend.
- 💃 Usando TypeScript, hooks, Vite, y otras partes de una stack moderna de frontend.
- 🎨 [Tailwind CSS](https://tailwindcss.com) y [shadcn/ui](https://ui.shadcn.com) para los componentes del frontend.
- 🤖 Un cliente de frontend generado automáticamente.
- 🧪 [Playwright](https://playwright.dev) para escribir pruebas End-to-End.
- 🦇 Soporte para modo oscuro.
- 💃 Usando TypeScript, hooks, Vite, y otras partes de una stack moderna de frontend.
- 🎨 [Tailwind CSS](https://tailwindcss.com) y [shadcn/ui](https://ui.shadcn.com) para los componentes del frontend.
- 🤖 Un cliente de frontend generado automáticamente.
- 🧪 [Playwright](https://playwright.dev) para escribir pruebas End-to-End.
- 🦇 Soporte para modo oscuro.
- 🐋 [Docker Compose](https://www.docker.com) para desarrollo y producción.
- 🔒 Hashing seguro de contraseñas por defecto.
- 🔑 Autenticación con tokens JWT.
- 🔑 Autenticación con JWT (JSON Web Token).
- 📫 Recuperación de contraseñas basada en email.
- ✅ Pruebas con [Pytest](https://pytest.org).
- 📞 [Traefik](https://traefik.io) como proxy inverso / load balancer.
+12 -12
View File
@@ -1,8 +1,8 @@
# Introducción a Tipos en Python { #python-types-intro }
Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "type hints").
Python tiene soporte para "anotaciones de tipos" opcionales (también llamadas "anotaciones de tipos").
Estas **"anotaciones de tipos"** o type hints son una sintaxis especial que permite declarar el <dfn title="por ejemplo: str, int, float, bool">tipo</dfn> de una variable.
Estas **"anotaciones de tipos"** o anotaciones son una sintaxis especial que permite declarar el <dfn title="por ejemplo: str, int, float, bool">tipo</dfn> de una variable.
Al declarar tipos para tus variables, los editores y herramientas te pueden proporcionar un mejor soporte.
@@ -44,7 +44,7 @@ Es un programa muy simple.
Pero ahora imagina que lo escribieras desde cero.
En algún momento habrías empezado la definición de la función, tenías los parámetros listos...
En algún momento empiezas a definir la función, y tienes los parámetros listos...
Pero luego tienes que llamar "ese método que convierte la primera letra a mayúscula".
@@ -58,7 +58,7 @@ Pero, tristemente, no obtienes nada útil:
<img src="/img/python-types/image01.png">
### Añadir tipos { #add-types }
### Añade tipos { #add-types }
Modifiquemos una sola línea de la versión anterior.
@@ -120,7 +120,7 @@ Ahora sabes que debes corregirlo, convertir `age` a un string con `str(age)`:
Acabas de ver el lugar principal para declarar anotaciones de tipos. Como parámetros de función.
Este también es el lugar principal donde los utilizarías con **FastAPI**.
Este también es el lugar principal donde las utilizarías con **FastAPI**.
### Tipos simples { #simple-types }
@@ -137,7 +137,7 @@ Puedes usar, por ejemplo:
### Módulo `typing` { #typing-module }
Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` de la standard library, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`:
Para algunos casos adicionales, podrías necesitar importar algunas cosas del módulo `typing` del paquete estándar, por ejemplo cuando quieres declarar que algo tiene "cualquier tipo", puedes usar `Any` de `typing`:
```python
from typing import Any
@@ -149,7 +149,7 @@ def some_function(data: Any):
### Tipos genéricos { #generic-types }
Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "lista de strings" se declararía `list[str]`.
Algunos tipos pueden tomar "parámetros de tipo" entre corchetes, para definir sus tipos internos, por ejemplo una "list de strings" se declararía `list[str]`.
Estos tipos que pueden tomar parámetros de tipo se llaman **Tipos Genéricos** o **Genéricos**.
@@ -160,7 +160,7 @@ Puedes usar los mismos tipos integrados como genéricos (con corchetes y tipos d
* `set`
* `dict`
#### Lista { #list }
#### List { #list }
Por ejemplo, vamos a definir una variable para ser una `list` de `str`.
@@ -168,7 +168,7 @@ Declara la variable, con la misma sintaxis de dos puntos (`:`).
Como tipo, pon `list`.
Como la lista es un tipo que contiene algunos tipos internos, los pones entre corchetes:
Como la `list` es un tipo que contiene algunos tipos internos, los pones entre corchetes:
{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *}
@@ -180,15 +180,15 @@ En este caso, `str` es el parámetro de tipo pasado a `list`.
///
Eso significa: "la variable `items` es una `list`, y cada uno de los ítems en esta lista es un `str`".
Eso significa: "la variable `items` es una `list`, y cada uno de los ítems en esta `list` es un `str`".
Al hacer eso, tu editor puede proporcionar soporte incluso mientras procesa elementos de la lista:
Al hacer eso, tu editor puede proporcionar soporte incluso mientras procesa elementos de la `list`:
<img src="/img/python-types/image05.png">
Sin tipos, eso es casi imposible de lograr.
Nota que la variable `item` es uno de los elementos en la lista `items`.
Nota que la variable `item` es uno de los elementos en la `list` `items`.
Y aún así, el editor sabe que es un `str` y proporciona soporte para eso.
+31 -19
View File
@@ -17,16 +17,16 @@ Digamos que tienes una estructura de archivos como esta:
```
.
├── app
   ├── __init__.py
   ├── main.py
   ├── dependencies.py
   └── routers
   │ ├── __init__.py
   │ ├── items.py
   │ └── users.py
   └── internal
   ├── __init__.py
   └── admin.py
├── __init__.py
├── main.py
├── dependencies.py
└── routers
│ ├── __init__.py
│ ├── items.py
│ └── users.py
└── internal
├── __init__.py
└── admin.py
```
/// tip | Consejo
@@ -181,12 +181,12 @@ El resultado final es que los paths de item son ahora:
...como pretendíamos.
* Serán marcados con una lista de tags que contiene un solo string `"items"`.
* Estos "tags" son especialmente útiles para los sistemas de documentación interactiva automática (usando OpenAPI).
* Estos "tags" son especialmente útiles para los sistemas de documentación interactiva automática (usando OpenAPI).
* Todos incluirán las `responses` predefinidas.
* Todas estas *path operations* tendrán la lista de `dependencies` evaluadas/ejecutadas antes de ellas.
* Si también declaras dependencias en una *path operation* específica, **también se ejecutarán**.
* Las dependencias del router se ejecutan primero, luego las [`dependencies` en el decorador](dependencies/dependencies-in-path-operation-decorators.md), y luego las dependencias de parámetros normales.
* También puedes agregar [dependencias de `Security` con `scopes`](../advanced/security/oauth2-scopes.md).
* Si también declaras dependencias en una *path operation* específica, **también se ejecutarán**.
* Las dependencias del router se ejecutan primero, luego las [`dependencies` en el decorador](dependencies/dependencies-in-path-operation-decorators.md), y luego las dependencias de parámetros normales.
* También puedes agregar [dependencias de `Security` con `scopes`](../advanced/security/oauth2-scopes.md).
/// tip | Consejo
@@ -396,9 +396,9 @@ Incluirá todas las rutas de ese router como parte de ella.
/// note | Detalles Técnicos
En realidad creará internamente una *path operation* para cada *path operation* que fue declarada en el `APIRouter`.
FastAPI mantiene activo el `APIRouter` original y sus `APIRoute`s cuando el router se incluye en la aplicación principal.
Así, detrás de escena, funcionará como si todo fuera la misma única app.
Eso significa que las subclases personalizadas de `APIRouter` y `APIRoute` aún pueden participar después de incluir el router.
///
@@ -406,7 +406,7 @@ Así, detrás de escena, funcionará como si todo fuera la misma única app.
No tienes que preocuparte por el rendimiento al incluir routers.
Esto tomará microsegundos y solo sucederá al inicio.
Esto está diseñado para ser liviano y evitar añadir sobrecarga a cada request.
Así que no afectará el rendimiento. ⚡
@@ -461,7 +461,7 @@ Los `APIRouter`s no están "montados", no están aislados del resto de la aplica
Esto se debe a que queremos incluir sus *path operations* en el esquema de OpenAPI y las interfaces de usuario.
Como no podemos simplemente aislarlos y "montarlos" independientemente del resto, las *path operations* se "clonan" (se vuelven a crear), no se incluyen directamente.
FastAPI mantiene los routers y path operations originales activos, y combina los prefijos del router, dependencias, tags, responses y otros metadatos al manejar requests y generar OpenAPI.
///
@@ -532,4 +532,16 @@ De la misma manera que puedes incluir un `APIRouter` en una aplicación `FastAPI
router.include_router(other_router)
```
Asegúrate de hacerlo antes de incluir `router` en la app de `FastAPI`, para que las *path operations* de `other_router` también se incluyan.
Puedes hacerlo antes o después de incluir `router` en la app de `FastAPI`. FastAPI seguirá incluyendo las *path operations* de `other_router` en el ruteo y en OpenAPI.
Lo mismo aplica a las *path operations* añadidas después a los routers. También serán visibles a través de la inclusión anterior.
/// warning | Detalles Técnicos
Evita mutar directamente `router.routes` después de incluir un router. FastAPI trata la inclusión de routers como “en vivo”, así que el router original y sus rutas siguen formando parte del ruteo y de la generación de OpenAPI.
Usa APIs documentadas como los decoradores de *path operations* y `.include_router()` para agregar rutas y routers.
Trata `router.routes` como un árbol de rutas de nivel bajo que puede contener definiciones de rutas y routers incluidos, y evita depender de él como una lista plana de *path operations* finales.
///
@@ -108,7 +108,7 @@ Por ejemplo:
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
/// info | Información
/// note | Nota
`Body` también tiene todos los mismos parámetros de validación y metadatos extras que `Query`, `Path` y otros que verás luego.
@@ -123,7 +123,7 @@ Por defecto, **FastAPI** esperará su cuerpo directamente.
Pero si deseas que espere un JSON con una clave `item` y dentro de ella los contenidos del modelo, como lo hace cuando declaras parámetros de cuerpo extra, puedes usar el parámetro especial `Body` `embed`:
```Python
item: Item = Body(embed=True)
item: Annotated[Item, Body(embed=True)]
```
como en:
+3 -3
View File
@@ -23,7 +23,7 @@ pasa el/los tipo(s) interno(s) como "parámetros de tipo" usando corchetes: `[`
my_list: list[str]
```
Eso es toda la sintaxis estándar de Python para declaraciones de tipo.
Esa 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.
@@ -136,7 +136,7 @@ Esto esperará (convertirá, validará, documentará, etc.) un cuerpo JSON como:
}
```
/// info | Información
/// note | Nota
Nota cómo la clave `images` ahora tiene una lista de objetos de imagen.
@@ -148,7 +148,7 @@ Puedes definir modelos anidados tan profundamente como desees:
{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *}
/// info | Información
/// note | Nota
Observa cómo `Offer` tiene una lista de `Item`s, que a su vez tienen una lista opcional de `Image`s
+2 -1
View File
@@ -1,5 +1,6 @@
# Request Body { #request-body }
Cuando necesitas enviar datos desde un cliente (digamos, un navegador) a tu API, los envías como un **request body**.
Un **request** body es un dato enviado por el cliente a tu API. Un **response** body es el dato que tu API envía al cliente.
@@ -8,7 +9,7 @@ Tu API casi siempre tiene que enviar un **response** body. Pero los clientes no
Para declarar un **request** body, usas modelos de [Pydantic](https://docs.pydantic.dev/) con todo su poder y beneficios.
/// info | Información
/// note | Nota
Para enviar datos, deberías usar uno de estos métodos: `POST` (el más común), `PUT`, `DELETE` o `PATCH`.
+1 -1
View File
@@ -32,7 +32,7 @@ Puedes ver las cookies definidas en la UI de la documentación en `/docs`:
<img src="/img/tutorial/cookie-param-models/image01.png">
</div>
/// info | Información
/// note | Nota
Ten en cuenta que, como los **navegadores manejan las cookies** de maneras especiales y detrás de escenas, **no** permiten fácilmente que **JavaScript** las toque.
+2 -2
View File
@@ -24,13 +24,13 @@ Pero recuerda que cuando importas `Query`, `Path`, `Cookie` y otros desde `fasta
///
/// info | Información
/// note | Nota
Para declarar cookies, necesitas usar `Cookie`, porque de lo contrario los parámetros serían interpretados como parámetros de query.
///
/// info | Información
/// note | Nota
Ten en cuenta que, como **los navegadores manejan las cookies** de formas especiales y por detrás, **no** permiten fácilmente que **JavaScript** las toque.
+4 -3
View File
@@ -1,5 +1,6 @@
# Depuración { #debugging }
Puedes conectar el depurador en tu editor, por ejemplo con Visual Studio Code o PyCharm.
## Llama a `uvicorn` { #call-uvicorn }
@@ -62,7 +63,7 @@ from myapp import app
# Algún código adicional
```
en ese caso, la variable creada automáticamente dentro de `myapp.py` no tendrá la variable `__name__` con un valor de `"__main__"`.
en ese caso, la variable creada automáticamente `__name__` dentro de `myapp.py` no tendrá el valor `"__main__"`.
Así que, la línea:
@@ -72,7 +73,7 @@ Así que, la línea:
no se ejecutará.
/// info | Información
/// note | Nota
Para más información, revisa [la documentación oficial de Python](https://docs.python.org/3/library/__main__.html).
@@ -88,7 +89,7 @@ Por ejemplo, en Visual Studio Code, puedes:
* Ir al panel de "Debug".
* "Add configuration...".
* Seleccionar "Python".
* Seleccionar "Python"
* Ejecutar el depurador con la opción "`Python: Current File (Integrated Terminal)`".
Luego, iniciará el servidor con tu código **FastAPI**, deteniéndose en tus puntos de interrupción, etc.
@@ -28,7 +28,7 @@ También puede ayudar a evitar confusiones para nuevos desarrolladores que vean
///
/// info | Información
/// note | Nota
En este ejemplo usamos headers personalizados inventados `X-Key` y `X-Token`.
@@ -170,7 +170,7 @@ participant tasks as Background tasks
end
```
/// info | Información
/// note | Nota
Solo **un response** será enviado al cliente. Podría ser uno de los responses de error o será el response de la *path operation*.
@@ -234,6 +234,7 @@ participant operation as Path Operation
Las dependencias con `yield` han evolucionado con el tiempo para cubrir diferentes casos de uso y corregir algunos problemas.
Si quieres ver qué ha cambiado en diferentes versiones de FastAPI, puedes leer más al respecto en la guía avanzada, en [Dependencias avanzadas - Dependencias con `yield`, `HTTPException`, `except` y Tareas en Background](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks).
## Context Managers { #context-managers }
### Qué son los "Context Managers" { #what-are-context-managers }
+3 -3
View File
@@ -1,6 +1,6 @@
# Dependencias { #dependencies }
**FastAPI** tiene un sistema de **<dfn title="también conocido como componentes, recursos, proveedores, servicios, inyectables">Inyección de Dependencias</dfn>** muy poderoso pero intuitivo.
**FastAPI** tiene un sistema de **<dfn title="también conocido como: componentes, recursos, proveedores, servicios, inyectables">Inyección de Dependencias</dfn>** muy poderoso pero intuitivo.
Está diseñado para ser muy simple de usar, y para hacer que cualquier desarrollador integre otros componentes con **FastAPI** de forma muy sencilla.
@@ -51,7 +51,7 @@ En este caso, esta dependencia espera:
Y luego solo devuelve un `dict` que contiene esos valores.
/// info | Información
/// note | Nota
FastAPI agregó soporte para `Annotated` (y comenzó a recomendarlo) en la versión 0.95.0.
@@ -106,7 +106,7 @@ common_parameters --> read_users
De esta manera escribes código compartido una vez y **FastAPI** se encarga de llamarlo para tus *path operations*.
/// check | Revisa
/// tip | Consejo
Nota que no tienes que crear una clase especial y pasarla en algún lugar a **FastAPI** para "registrarla" o algo similar.
@@ -35,7 +35,7 @@ Entonces podemos usar la dependencia con:
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *}
/// info | Información
/// note | Nota
Fíjate que solo estamos declarando una dependencia en la *path operation function*, `query_or_cookie_extractor`.
@@ -1,5 +1,6 @@
# Tipos de Datos Extra { #extra-data-types }
Hasta ahora, has estado usando tipos de datos comunes, como:
* `int`
+1 -1
View File
@@ -208,4 +208,4 @@ En este caso, puedes usar `dict`:
Usa múltiples modelos Pydantic y hereda libremente para cada caso.
No necesitas tener un solo modelo de datos por entidad si esa entidad debe poder tener diferentes "estados". Como el caso con la "entidad" usuario con un estado que incluye `password`, `password_hash` y sin contraseña.
No necesitas tener un solo modelo de datos por entidad si esa entidad debe poder tener diferentes "estados". La "entidad" **usuario** es un ejemplo, con estados que incluyen `password`, `password_hash` o ninguna contraseña.
+16 -24
View File
@@ -90,13 +90,13 @@ Verás la documentación alternativa automática (proporcionada por [ReDoc](http
Un "esquema" es una definición o descripción de algo. No el código que lo implementa, sino solo una descripción abstracta.
#### Esquema de la API { #api-schema }
#### "Esquema" de la API { #api-schema }
En este caso, [OpenAPI](https://github.com/OAI/OpenAPI-Specification) es una especificación que dicta cómo definir un esquema de tu API.
Esta definición de esquema incluye los paths de tu API, los posibles parámetros que toman, etc.
#### Esquema de Datos { #data-schema }
#### "Esquema" de datos { #data-schema }
El término "esquema" también podría referirse a la forma de algunos datos, como el contenido JSON.
@@ -180,7 +180,7 @@ lo cual sería equivalente a:
from backend.main import app
```
### `fastapi dev` con path { #fastapi-dev-with-path }
### `fastapi dev` con path o con la opción de CLI `--entrypoint` { #fastapi-dev-with-path-or-with-entrypoint-cli-option }
También puedes pasar el path del archivo al comando `fastapi dev`, y adivinará el objeto app de FastAPI que debe usar:
@@ -188,29 +188,19 @@ También puedes pasar el path del archivo al comando `fastapi dev`, y adivinará
$ fastapi dev main.py
```
Pero tendrías que recordar pasar el path correcto cada vez que llames al comando `fastapi`.
O, también puedes pasar la opción `--entrypoint` al comando `fastapi dev`:
```console
$ fastapi dev --entrypoint main:app
```
Pero tendrías que recordar pasar el path\entrypoint correcto cada vez que llames al comando `fastapi`.
Además, otras herramientas podrían no ser capaces de encontrarlo, por ejemplo la [Extensión de VS Code](../editor-support.md) o [FastAPI Cloud](https://fastapicloud.com), así que se recomienda usar el `entrypoint` en `pyproject.toml`.
### Despliega tu app (opcional) { #deploy-your-app-optional }
Opcionalmente puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com), ve y únete a la lista de espera si aún no lo has hecho. 🚀
Si ya tienes una cuenta de **FastAPI Cloud** (te invitamos desde la lista de espera 😉), puedes desplegar tu aplicación con un solo comando.
Antes de desplegar, asegúrate de haber iniciado sesión:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
Luego despliega tu app:
Opcionalmente puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con un solo comando. 🚀
<div class="termy">
@@ -226,6 +216,8 @@ Deploying to FastAPI Cloud...
</div>
La CLI detectará automáticamente tu aplicación de FastAPI y la desplegará en la nube. Si no has iniciado sesión, se abrirá tu navegador para completar el proceso de autenticación.
¡Eso es todo! Ahora puedes acceder a tu app en esa URL. ✨
## Recapitulación, paso a paso { #recap-step-by-step }
@@ -270,7 +262,7 @@ https://example.com/items/foo
/items/foo
```
/// info | Información
/// note | Nota
Un "path" también es comúnmente llamado "endpoint" o "ruta".
@@ -309,7 +301,7 @@ Normalmente usas:
* `PUT`: para actualizar datos.
* `DELETE`: para eliminar datos.
Así que, en OpenAPI, cada uno de los métodos HTTP se llama una "operation".
Así que, en OpenAPI, cada uno de los métodos HTTP se llama una "operación".
Vamos a llamarlas "**operaciones**" también.
@@ -322,7 +314,7 @@ El `@app.get("/")` le dice a **FastAPI** que la función justo debajo se encarga
* el path `/`
* usando una <dfn title="un método HTTP GET"><code>get</code> operación</dfn>
/// info | Información sobre `@decorator`
/// note | Información sobre `@decorator`
Esa sintaxis `@algo` en Python se llama un "decorador".
+133
View File
@@ -0,0 +1,133 @@
# Frontend { #frontend }
Puedes servir apps frontend estáticas con `app.frontend()` (o `router.frontend()`).
Esto es útil para herramientas de frontend que generan archivos estáticos, como React con Vite, TanStack Router, Astro, Vue, Svelte, Angular, Solid y otras.
Con estas herramientas, normalmente tienes un paso que construye el frontend, con un comando como:
```bash
npm run build
```
Eso generaría un directorio como `./dist/` con tus archivos frontend.
Puedes usar `app.frontend()` para servir ese directorio siguiendo las convenciones que necesitan estos frameworks frontend.
**FastAPI** revisa primero las *path operations*. Los archivos frontend se revisan solo si ninguna ruta normal coincide, así que tu API no se verá afectada.
## Sirve un Frontend { #serve-a-frontend }
Después de construir tu frontend, por ejemplo con `npm run build`, pon los archivos generados en un directorio, por ejemplo, `dist`.
La estructura de tu proyecto podría verse así:
```text
.
├── pyproject.toml
├── app
│ ├── __init__.py
│ └── main.py
└── dist
├── index.html
└── assets
└── app.js
```
Luego sírvelo con `app.frontend()`:
{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *}
Con esto, un request a `/assets/app.js` puede servir `dist/assets/app.js`.
Si también tienes una *path operation* de **FastAPI**, la *path operation* gana.
## Routing del lado del cliente { #client-side-routing }
Muchas apps frontend, incluidas las **single-page apps** (SPAs), usan routing del lado del cliente. Un path como `/dashboard/settings` podría no ser un archivo real, pero el framework se encargaría de manejarlo.
Entonces, si se accede a esa URL directamente (en lugar de navegar por la app), el backend debería servir la app frontend desde `index.html`, para que el framework frontend pueda manejar el routing del lado del cliente.
Para eso, usa `fallback="index.html"`:
{* ../../docs_src/frontend/tutorial002_py310.py hl[5] *}
**FastAPI** usa este fallback solo para requests `GET` y `HEAD` que parecen navegación del navegador. Los archivos faltantes como JavaScript, CSS e imágenes siguen devolviendo `404`.
Los requests con otros métodos, como `POST` o `PUT`, a paths que solo coinciden con el fallback del frontend también devuelven `404`. Las *path operations* normales de **FastAPI** siguen teniendo mayor prioridad que las rutas frontend.
/// tip | Consejo
Por defecto, `fallback` tiene un valor de `fallback="auto"`. En la mayoría de los casos no necesitarás especificar `fallback`. Lee más abajo para los detalles.
///
Esto es lo que querrías con muchas apps frontend que usan routing del lado del cliente, por ejemplo, React con TanStack Router, Vue, Angular, SvelteKit o Solid.
## Página 404 personalizada { #custom-404-page }
También puedes servir una página estática `404.html` para paths frontend faltantes:
{* ../../docs_src/frontend/tutorial003_py310.py hl[5] *}
Esa response mantiene un código de estado `404`.
En este caso, **FastAPI** no servirá `index.html` para paths frontend faltantes. En su lugar, devolverá el archivo `404.html`.
/// tip | Consejo
Por defecto, `fallback` tiene un valor de `fallback="auto"`. Con esto, si se encuentra un archivo `404.html`, se usará automáticamente como fallback.
Así que normalmente puedes omitir el argumento `fallback`.
///
Esto es útil con herramientas de frontend que generan archivos HTML estáticos para cada página, como Astro.
## Fallback automático { #fallback-auto }
Por defecto, `app.frontend()` usa `fallback="auto"`.
Si hay un archivo `404.html` en el directorio frontend, los paths frontend faltantes sirven ese archivo con código de estado `404`.
De lo contrario, si hay un archivo `index.html`, los paths faltantes de navegación del navegador sirven `index.html`, que es lo que muchas apps frontend con routing del lado del cliente esperan.
Así que, en la mayoría de los casos, puedes usar `app.frontend("/", directory="dist")` sin especificar el argumento `fallback`.
{* ../../docs_src/frontend/tutorial001_py310.py hl[5] *}
## Desactiva el fallback { #disable-fallback }
Si no quieres servir un archivo fallback para paths frontend faltantes, usa `fallback=None`:
{* ../../docs_src/frontend/tutorial005_py310.py hl[5] *}
Entonces los paths frontend faltantes devuelven el `404` normal.
## Revisa el directorio { #check-directory }
Por defecto, `app.frontend()` revisa que el directorio exista cuando se crea la app.
Esto ayuda a detectar errores de configuración temprano. Por ejemplo, si falta el directorio de salida del build del frontend, **FastAPI** lanzará un error al iniciar.
Si tus archivos frontend se crean más tarde, por ejemplo mediante un paso de build separado después de crear el objeto app, configura `check_dir=False`:
{* ../../docs_src/frontend/tutorial006_py310.py hl[5] *}
Con `check_dir=False`, **FastAPI** no revisará el directorio cuando se cree la app. Si el directorio configurado todavía falta cuando se maneja un request, **FastAPI** lanzará un error en ese momento.
## Úsalo con `APIRouter` { #use-it-with-apirouter }
También puedes agregar archivos frontend a un `APIRouter` e incluirlo con un prefijo:
{* ../../docs_src/frontend/tutorial004_py310.py hl[6,7] *}
En este ejemplo, los paths frontend se sirven bajo `/app`.
Cualquier *path operation* regular en la app seguirá teniendo prioridad, incluso en otros routers.
## Solo salida estática del build { #static-build-output-only }
`app.frontend()` sirve archivos ya generados por tu build del frontend.
No ejecuta renderizado del lado del servidor. Es para frameworks frontend que generan archivos estáticos, no para frameworks que necesitan renderizado dinámico en el servidor para cada request.
+8 -8
View File
@@ -101,7 +101,7 @@ Así que recibirás un error limpio, con un código de estado HTTP de `418` y un
{"message": "Oops! yolo did something. There goes a rainbow..."}
```
/// note | Nota Técnica
/// note | Detalles Técnicos
También podrías usar `from starlette.requests import Request` y `from starlette.responses import JSONResponse`.
@@ -109,11 +109,11 @@ También podrías usar `from starlette.requests import Request` y `from starlett
///
## Sobrescribir los manejadores de excepciones predeterminados { #override-the-default-exception-handlers }
## Sobrescribir los manejadores de excepciones por defecto { #override-the-default-exception-handlers }
**FastAPI** tiene algunos manejadores de excepciones predeterminados.
**FastAPI** tiene algunos manejadores de excepciones por defecto.
Estos manejadores se encargan de devolver los responses JSON predeterminadas cuando lanzas un `HTTPException` y cuando el request tiene datos inválidos.
Estos manejadores se encargan de devolver los responses JSON por defecto cuando lanzas un `HTTPException` y cuando el request tiene datos inválidos.
Puedes sobrescribir estos manejadores de excepciones con los tuyos propios.
@@ -121,7 +121,7 @@ Puedes sobrescribir estos manejadores de excepciones con los tuyos propios.
Cuando un request contiene datos inválidos, **FastAPI** lanza internamente un `RequestValidationError`.
Y también incluye un manejador de excepciones predeterminado para ello.
Y también incluye un manejador de excepciones por defecto para ello.
Para sobrescribirlo, importa el `RequestValidationError` y úsalo con `@app.exception_handler(RequestValidationError)` para decorar el manejador de excepciones.
@@ -161,7 +161,7 @@ Por ejemplo, podrías querer devolver un response de texto plano en lugar de JSO
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *}
/// note | Nota Técnica
/// note | Detalles Técnicos
También podrías usar `from starlette.responses import PlainTextResponse`.
@@ -237,8 +237,8 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
### Reutilizar los manejadores de excepciones de **FastAPI** { #reuse-fastapis-exception-handlers }
Si quieres usar la excepción junto con los mismos manejadores de excepciones predeterminados de **FastAPI**, puedes importar y reutilizar los manejadores de excepciones predeterminados de `fastapi.exception_handlers`:
Si quieres usar la excepción junto con los mismos manejadores de excepciones por defecto de **FastAPI**, puedes importar y reutilizar los manejadores de excepciones por defecto de `fastapi.exception_handlers`:
{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *}
En este ejemplo solo estás `print`eando el error con un mensaje muy expresivo, pero te haces una idea. Puedes usar la excepción y luego simplemente reutilizar los manejadores de excepciones predeterminados.
En este ejemplo solo estás `print`eando el error con un mensaje muy expresivo, pero te haces una idea. Puedes usar la excepción y luego simplemente reutilizar los manejadores de excepciones por defecto.
+1 -1
View File
@@ -54,7 +54,7 @@ $ <font color="#4E9A06">fastapi</font> dev
Es **ALTAMENTE recomendable** que escribas o copies el código, lo edites y lo ejecutes localmente.
Usarlo en tu editor es lo que realmente te muestra los beneficios de FastAPI, al ver cuán poco código tienes que escribir, todos los chequeos de tipos, autocompletado, etc.
Usarlo en tu editor es lo que realmente te muestra los beneficios de FastAPI, al ver cuán poco código tienes que escribir, todo el chequeo de tipos, autocompletado, etc.
---
+4 -4
View File
@@ -1,4 +1,4 @@
# Metadata y URLs de Docs { #metadata-and-docs-urls }
# Metadata y URLs de documentación { #metadata-and-docs-urls }
Puedes personalizar varias configuraciones de metadata en tu aplicación **FastAPI**.
@@ -11,7 +11,7 @@ Puedes establecer los siguientes campos que se usan en la especificación OpenAP
| `title` | `str` | El título de la API. |
| `summary` | `str` | Un resumen corto de la API. <small>Disponible desde OpenAPI 3.1.0, FastAPI 0.99.0.</small> |
| `description` | `str` | Una breve descripción de la API. Puede usar Markdown. |
| `version` | `string` | La versión de la API. Esta es la versión de tu propia aplicación, no de OpenAPI. Por ejemplo, `2.5.0`. |
| `version` | `str` | La versión de la API. Esta es la versión de tu propia aplicación, no de OpenAPI. Por ejemplo, `2.5.0`. |
| `terms_of_service` | `str` | Una URL a los Términos de Servicio para la API. Si se proporciona, debe ser una URL. |
| `contact` | `dict` | La información de contacto para la API expuesta. Puede contener varios campos. <details><summary><code>contact</code> fields</summary><table><thead><tr><th>Parámetro</th><th>Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>El nombre identificativo de la persona/organización de contacto.</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>La URL que apunta a la información de contacto. DEBE tener el formato de una URL.</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>La dirección de correo electrónico de la persona/organización de contacto. DEBE tener el formato de una dirección de correo.</td></tr></tbody></table></details> |
| `license_info` | `dict` | La información de la licencia para la API expuesta. Puede contener varios campos. <details><summary><code>license_info</code> fields</summary><table><thead><tr><th>Parámetro</th><th>Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>REQUERIDO</strong> (si se establece un <code>license_info</code>). El nombre de la licencia utilizada para la API.</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>Una expresión de licencia [SPDX](https://spdx.org/licenses/) para la API. El campo <code>identifier</code> es mutuamente excluyente del campo <code>url</code>. <small>Disponible desde OpenAPI 3.1.0, FastAPI 0.99.0.</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>Una URL a la licencia utilizada para la API. DEBE tener el formato de una URL.</td></tr></tbody></table></details> |
@@ -74,7 +74,7 @@ Usa el parámetro `tags` con tus *path operations* (y `APIRouter`s) para asignar
{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *}
/// info | Información
/// note | Nota
Lee más sobre etiquetas en [Configuración de Path Operation](path-operation-configuration.md#tags).
@@ -104,7 +104,7 @@ Por ejemplo, para configurarlo para que se sirva en `/api/v1/openapi.json`:
Si quieres deshabilitar el esquema OpenAPI completamente, puedes establecer `openapi_url=None`, eso también deshabilitará las interfaces de usuario de documentación que lo usan.
## URLs de Docs { #docs-urls }
## URLs de documentación { #docs-urls }
Puedes configurar las dos interfaces de usuario de documentación incluidas:
@@ -56,7 +56,7 @@ Puedes añadir un `summary` y `description`:
## Descripción desde docstring { #description-from-docstring }
Como las descripciones tienden a ser largas y cubrir múltiples líneas, puedes declarar la descripción de la *path operation* en la <dfn title="un string de múltiples líneas como la primera expresión dentro de una función (no asignada a ninguna variable) usada para documentación">docstring</dfn> de la función y **FastAPI** la leerá desde allí.
Como las descripciones tienden a ser largas y cubrir múltiples líneas, puedes declarar la descripción de la *path operation* en la <dfn title="un string de múltiples líneas como la primera expresión dentro de una función (no asignada a ninguna variable) usado para documentación">docstring</dfn> de la función y **FastAPI** la leerá desde allí.
Puedes escribir [Markdown](https://en.wikipedia.org/wiki/Markdown) en el docstring, se interpretará y mostrará correctamente (teniendo en cuenta la indentación del docstring).
@@ -72,13 +72,13 @@ Puedes especificar la descripción del response con el parámetro `response_desc
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
/// info | Información
/// note | Nota
Ten en cuenta que `response_description` se refiere específicamente al response, mientras que `description` se refiere a la *path operation* en general.
///
/// check | Revisa
/// tip | Consejo
OpenAPI especifica que cada *path operation* requiere una descripción de response.
@@ -90,11 +90,11 @@ Entonces, si no proporcionas una, **FastAPI** generará automáticamente una de
## Deprecar una *path operation* { #deprecate-a-path-operation }
Si necesitas marcar una *path operation* como <dfn title="obsoleta, se recomienda no usarla">deprecated</dfn>, pero sin eliminarla, pasa el parámetro `deprecated`:
Si necesitas marcar una *path operation* como <dfn title="obsoleta, se recomienda no usarla">obsoleta</dfn>, pero sin eliminarla, pasa el parámetro `deprecated`:
{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *}
Se marcará claramente como deprecado en la documentación interactiva:
Se marcará claramente como deprecated en la documentación interactiva:
<img src="/img/tutorial/path-operation-configuration/image04.png">
@@ -8,7 +8,7 @@ Primero, importa `Path` de `fastapi`, e importa `Annotated`:
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *}
/// info | Información
/// note | Nota
FastAPI agregó soporte para `Annotated` (y comenzó a recomendar su uso) en la versión 0.95.0.
@@ -131,7 +131,7 @@ Y también puedes declarar validaciones numéricas:
* `lt`: `l`ess `t`han
* `le`: `l`ess than or `e`qual
/// info | Información
/// note | Nota
`Query`, `Path` y otras clases que verás más adelante son subclases de una clase común `Param`.
+5 -5
View File
@@ -20,7 +20,7 @@ Puedes declarar el tipo de un parámetro de path en la función, usando anotacio
En este caso, `item_id` se declara como un `int`.
/// check | Revisa
/// tip | Consejo
Esto te dará soporte del editor dentro de tu función, con chequeo de errores, autocompletado, etc.
@@ -34,7 +34,7 @@ Si ejecutas este ejemplo y abres tu navegador en [http://127.0.0.1:8000/items/3]
{"item_id":3}
```
/// check | Revisa
/// tip | Consejo
Nota que el valor que tu función recibió (y devolvió) es `3`, como un `int` de Python, no un string `"3"`.
@@ -66,7 +66,7 @@ porque el parámetro de path `item_id` tenía un valor de `"foo"`, que no es un
El mismo error aparecería si proporcionaras un `float` en lugar de un `int`, como en: [http://127.0.0.1:8000/items/4.2](http://127.0.0.1:8000/items/4.2)
/// check | Revisa
/// tip | Consejo
Entonces, con la misma declaración de tipo de Python, **FastAPI** te ofrece validación de datos.
@@ -82,7 +82,7 @@ Y cuando abras tu navegador en [http://127.0.0.1:8000/docs](http://127.0.0.1:800
<img src="/img/tutorial/path-params/image01.png">
/// check | Revisa
/// tip | Consejo
Nuevamente, solo con esa misma declaración de tipo de Python, **FastAPI** te ofrece documentación automática e interactiva (integrando Swagger UI).
@@ -130,7 +130,7 @@ La primera siempre será utilizada ya que el path coincide primero.
## Valores predefinidos { #predefined-values }
Si tienes una *path operation* que recibe un *path parameter*, pero quieres que los valores posibles válidos del *path parameter* estén predefinidos, puedes usar un <abbr title="Enumeration Enumeración">`Enum`</abbr> estándar de Python.
Si tienes una *path operation* que recibe un *path parameter*, pero quieres que los valores posibles válidos del *path parameter* estén predefinidos, puedes usar un <abbr title="Enumeración">`Enum`</abbr> estándar de Python.
### Crear una clase `Enum` { #create-an-enum-class }
@@ -18,7 +18,7 @@ Tener `str | None` permitirá que tu editor te dé un mejor soporte y detecte er
## Validaciones adicionales { #additional-validation }
Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, su longitud no exceda los 50 caracteres.
Vamos a hacer que, aunque `q` sea opcional, siempre que se proporcione, **su longitud no exceda los 50 caracteres**.
### Importar `Query` y `Annotated` { #import-query-and-annotated }
@@ -29,7 +29,7 @@ Para lograr eso, primero importa:
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
/// info | Información
/// note | Nota
FastAPI añadió soporte para `Annotated` (y empezó a recomendarlo) en la versión 0.95.0.
@@ -69,7 +69,7 @@ Ahora que tenemos este `Annotated` donde podemos poner más información (en est
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. 😎
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
@@ -79,9 +79,9 @@ Aquí estamos usando `Query()` porque este es un **parámetro de query**. Más a
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)
* **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 esquema de OpenAPI *path operation* (así aparecerá en la **UI de documentación automática**)
## Alternativa (antigua): `Query` como valor por defecto { #alternative-old-query-as-the-default-value }
@@ -120,7 +120,7 @@ Luego, podemos pasar más parámetros a `Query`. En este caso, el parámetro `ma
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.
Esto validará los datos, mostrará un error claro cuando los datos no sean válidos, y documentará el parámetro en el esquema de OpenAPI *path operation*.
### `Query` como valor por defecto o en `Annotated` { #query-as-the-default-value-or-in-annotated }
@@ -150,13 +150,13 @@ q: str = Query(default="rick")
### Ventajas de `Annotated` { #advantages-of-annotated }
Usar `Annotated` es recomendado en lugar del valor por defecto en los parámetros de función, es mejor por múltiples razones. 🤓
**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. 😌
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.
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.
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 las operaciones internas generen errores.
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](https://typer.tiangolo.com/). 🚀
@@ -172,13 +172,13 @@ Puedes definir una <dfn title="Una expresión regular, regex o regexp es una sec
{* ../../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:
Este patrón específico de expresión regular revisa 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.
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**.
@@ -296,9 +296,9 @@ También puedes usar `list` directamente en lugar de `list[str]`:
/// note | Nota
Ten en cuenta que en este caso, FastAPI no comprobará el contenido de la list.
Ten en cuenta que en este caso, FastAPI no revisará el contenido de la list.
Por ejemplo, `list[int]` comprobaría (y documentaría) que el contenido de la list son enteros. Pero `list` sola no lo haría.
Por ejemplo, `list[int]` revisaría (y documentaría) que el contenido de la list son enteros. Pero `list` sola no lo haría.
///
@@ -366,9 +366,9 @@ Para excluir un parámetro de query del esquema de OpenAPI generado (y por lo ta
## Validación personalizada { #custom-validation }
Podría haber casos donde necesites hacer alguna validación personalizada que no puede hacerse con los parámetros mostrados arriba.
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`).
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](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) dentro de `Annotated`.
@@ -378,11 +378,11 @@ Pydantic también tiene [`BeforeValidator`](https://docs.pydantic.dev/latest/con
///
Por ejemplo, este validador personalizado comprueba que el ID del ítem empiece con `isbn-` para un número de libro <abbr title="International Standard Book Number - Número Estándar Internacional de Libros">ISBN</abbr> o con `imdb-` para un ID de URL de película de <abbr title="Internet Movie Database - Base de datos de películas en Internet: un sitio web con información sobre películas">IMDB</abbr>:
Por ejemplo, este validador personalizado revisa que el ID del ítem empiece con `isbn-` para un número de libro <abbr title="International Standard Book Number - Número Estándar Internacional de Libros">ISBN</abbr> o con `imdb-` para un ID de URL de película de <abbr title="Internet Movie Database - Base de datos de películas en Internet: un sitio web con información sobre películas">IMDB</abbr>:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
/// info | Información
/// note | Nota
Esto está disponible con Pydantic versión 2 o superior. 😎
@@ -390,15 +390,15 @@ 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.
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.
Estos validadores personalizados son para cosas que pueden revisarse **solo** con los **mismos datos** provistos en el request.
///
### Entiende ese código { #understand-that-code }
El punto importante es solo usar `AfterValidator` con una función dentro de `Annotated`. Si quieres, sáltate esta parte. 🤸
El punto importante es solo usar **`AfterValidator` con una función dentro de `Annotated`**. Si quieres, sáltate esta parte. 🤸
---
@@ -406,7 +406,7 @@ Pero si te da curiosidad este ejemplo de código específico y sigues entretenid
#### String con `value.startswith()` { #string-with-value-startswith }
¿Lo notaste? un string usando `value.startswith()` puede recibir una tupla, y comprobará cada valor en la tupla:
¿Lo notaste? Un string usando `value.startswith()` puede recibir una tupla, y revisará cada valor en la tupla:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
@@ -416,13 +416,13 @@ Con `data.items()` obtenemos un <dfn title="Algo que podemos iterar con un for l
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 con `random.choice()` podemos obtener un **valor aleatorio** de la list, 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`.
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? 🐍
...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] *}
+2 -1
View File
@@ -65,7 +65,7 @@ De la misma manera, puedes declarar parámetros de query opcionales, establecien
En este caso, el parámetro de función `q` será opcional y será `None` por defecto.
/// check | Revisa
/// tip | Consejo
Además, nota que **FastAPI** es lo suficientemente inteligente para notar que el parámetro de path `item_id` es un parámetro de path y `q` no lo es, por lo tanto, es un parámetro de query.
@@ -109,6 +109,7 @@ http://127.0.0.1:8000/items/foo?short=yes
o cualquier otra variación (mayúsculas, primera letra en mayúscula, etc.), tu función verá el parámetro `short` con un valor `bool` de `True`. De lo contrario, será `False`.
## Múltiples parámetros de path y de query { #multiple-path-and-query-parameters }
Puedes declarar múltiples parámetros de path y de query al mismo tiempo, **FastAPI** sabe cuál es cuál.
+5 -5
View File
@@ -2,7 +2,7 @@
Puedes definir archivos que serán subidos por el cliente utilizando `File`.
/// info | Información
/// note | Nota
Para recibir archivos subidos, primero instala [`python-multipart`](https://github.com/Kludex/python-multipart).
@@ -16,19 +16,19 @@ Esto es porque los archivos subidos se envían como "form data".
///
## Importar `File` { #import-file }
## Importa `File` { #import-file }
Importa `File` y `UploadFile` desde `fastapi`:
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *}
## Definir Parámetros `File` { #define-file-parameters }
## Define Parámetros `File` { #define-file-parameters }
Crea parámetros de archivo de la misma manera que lo harías para `Body` o `Form`:
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
/// info | Información
/// note | Nota
`File` es una clase que hereda directamente de `Form`.
@@ -117,7 +117,7 @@ La manera en que los formularios de HTML (`<form></form>`) envían los datos al
/// note | Detalles Técnicos
Los datos de los forms normalmente se codifican usando el "media type" `application/x-www-form-urlencoded` cuando no incluyen archivos.
Los datos de los formularios normalmente se codifican usando el "media type" `application/x-www-form-urlencoded` cuando no incluyen archivos.
Pero cuando el formulario incluye archivos, se codifica como `multipart/form-data`. Si usas `File`, **FastAPI** sabrá que tiene que obtener los archivos de la parte correcta del cuerpo.
+1 -1
View File
@@ -2,7 +2,7 @@
Puedes usar **modelos de Pydantic** para declarar **campos de formulario** en FastAPI.
/// info | Información
/// note | Nota
Para usar formularios, primero instala [`python-multipart`](https://github.com/Kludex/python-multipart).
@@ -2,7 +2,7 @@
Puedes definir archivos y campos de formulario al mismo tiempo usando `File` y `Form`.
/// info | Información
/// note | Nota
Para recibir archivos subidos y/o form data, primero instala [`python-multipart`](https://github.com/Kludex/python-multipart).
+7 -7
View File
@@ -1,8 +1,8 @@
# Datos de formulario { #form-data }
# Form Data { #form-data }
Cuando necesitas recibir campos de formulario en lugar de JSON, puedes usar `Form`.
/// info | Información
/// note | Nota
Para usar formularios, primero instala [`python-multipart`](https://github.com/Kludex/python-multipart).
@@ -14,13 +14,13 @@ $ pip install python-multipart
///
## Importar `Form` { #import-form }
## Importa `Form` { #import-form }
Importar `Form` desde `fastapi`:
Importa `Form` desde `fastapi`:
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *}
## Definir parámetros de `Form` { #define-form-parameters }
## Define parámetros de `Form` { #define-form-parameters }
Crea parámetros de formulario de la misma manera que lo harías para `Body` o `Query`:
@@ -32,7 +32,7 @@ La <dfn title="especificación">especificación</dfn> requiere que los campos se
Con `Form` puedes declarar las mismas configuraciones que con `Body` (y `Query`, `Path`, `Cookie`), incluyendo validación, ejemplos, un alias (por ejemplo, `user-name` en lugar de `username`), etc.
/// info | Información
/// note | Nota
`Form` es una clase que hereda directamente de `Body`.
@@ -70,4 +70,4 @@ Esto no es una limitación de **FastAPI**, es parte del protocolo HTTP.
## Recapitulación { #recap }
Usa `Form` para declarar parámetros de entrada de datos de formulario.
Usa `Form` para declarar parámetros de entrada de form data.
+2 -2
View File
@@ -72,7 +72,7 @@ Aquí estamos declarando un modelo `UserIn`, contendrá una contraseña en texto
{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *}
/// info | Información
/// note | Nota
Para usar `EmailStr`, primero instala [`email-validator`](https://github.com/JoshData/python-email-validator).
@@ -251,7 +251,7 @@ Entonces, si envías un request a esa *path operation* para el ítem con ID `foo
}
```
/// info | Información
/// note | Nota
También puedes usar:
@@ -1,5 +1,6 @@
# Código de Estado del Response { #response-status-code }
De la misma manera que puedes especificar un modelo de response, también puedes declarar el código de estado HTTP usado para el response con el parámetro `status_code` en cualquiera de las *path operations*:
* `@app.get()`
@@ -18,7 +19,7 @@ Observa que `status_code` es un parámetro del método "decorador" (`get`, `post
El parámetro `status_code` recibe un número con el código de estado HTTP.
/// info | Información
/// note | Nota
`status_code` también puede recibir un `IntEnum`, como por ejemplo el [`http.HTTPStatus`](https://docs.python.org/3/library/http.html#http.HTTPStatus) de Python.
@@ -1,4 +1,4 @@
# Declarar Datos de Ejemplo de Request { #declare-request-example-data }
# Declara Datos de Ejemplo de Request { #declare-request-example-data }
Puedes declarar ejemplos de los datos que tu aplicación puede recibir.
@@ -24,7 +24,7 @@ Por ejemplo, podrías usarlo para añadir metadatos para una interfaz de usuario
///
/// info | Información
/// note | Nota
OpenAPI 3.1.0 (usado desde FastAPI 0.99.0) añadió soporte para `examples`, que es parte del estándar de **JSON Schema**.
@@ -155,7 +155,7 @@ OpenAPI también añadió los campos `example` y `examples` a otras partes de la
* `File()`
* `Form()`
/// info | Información
/// note | Nota
Este viejo parámetro `examples` específico de OpenAPI ahora es `openapi_examples` desde FastAPI `0.103.0`.
@@ -171,7 +171,7 @@ Y ahora este nuevo campo `examples` tiene precedencia sobre el viejo campo únic
Este nuevo campo `examples` en JSON Schema es **solo una `list`** de ejemplos, no un dict con metadatos adicionales como en los otros lugares en OpenAPI (descritos arriba).
/// info | Información
/// note | Nota
Incluso después de que OpenAPI 3.1.0 fue lanzado con esta nueva integración más sencilla con JSON Schema, por un tiempo, Swagger UI, la herramienta que proporciona la documentación automática, no soportaba OpenAPI 3.1.0 (lo hace desde la versión 5.0.0 🎉).
@@ -24,7 +24,7 @@ Copia el ejemplo en un archivo `main.py`:
## Ejecútalo { #run-it }
/// info | Información
/// note | Nota
El paquete [`python-multipart`](https://github.com/Kludex/python-multipart) se instala automáticamente con **FastAPI** cuando ejecutas el comando `pip install "fastapi[standard]"`.
@@ -60,7 +60,7 @@ Verás algo así:
<img src="/img/tutorial/security/image01.png">
/// check | ¡Botón de autorización!
/// tip | ¡Botón de autorización!
Ya tienes un nuevo y brillante botón de "Authorize".
@@ -118,7 +118,7 @@ Así que, revisémoslo desde ese punto de vista simplificado:
En este ejemplo vamos a usar **OAuth2**, con el flujo **Password**, usando un token **Bearer**. Hacemos eso utilizando la clase `OAuth2PasswordBearer`.
/// info | Información
/// note | Nota
Un token "bearer" no es la única opción.
@@ -146,9 +146,9 @@ Usar una URL relativa es importante para asegurarse de que tu aplicación siga f
Este parámetro no crea ese endpoint / *path operation*, pero declara que la URL `/token` será la que el cliente deberá usar para obtener el token. Esa información se usa en OpenAPI, y luego en los sistemas de documentación interactiva del API.
Pronto también crearemos la verdadera *path operation*.
Pronto también crearemos la path operation real.
/// info | Información
/// note | Nota
Si eres un "Pythonista" muy estricto, tal vez no te guste el estilo del nombre del parámetro `tokenUrl` en lugar de `token_url`.
@@ -174,13 +174,13 @@ Ahora puedes pasar ese `oauth2_scheme` en una dependencia con `Depends`.
Esta dependencia proporcionará un `str` que se asigna al parámetro `token` de la *path operation function*.
**FastAPI** sabrá que puede usar esta dependencia para definir un "security scheme" en el esquema OpenAPI (y en los docs automáticos del API).
**FastAPI** sabrá que puede usar esta dependencia para definir un "security scheme" en el esquema OpenAPI (y en la documentación automática de la API).
/// info | Detalles técnicos
/// note | Detalles técnicos
**FastAPI** sabrá que puede usar la clase `OAuth2PasswordBearer` (declarada en una dependencia) para definir el esquema de seguridad en OpenAPI porque hereda de `fastapi.security.oauth2.OAuth2`, que a su vez hereda de `fastapi.security.base.SecurityBase`.
Todas las utilidades de seguridad que se integran con OpenAPI (y los docs automáticos del API) heredan de `SecurityBase`, así es como **FastAPI** puede saber cómo integrarlas en OpenAPI.
Todas las utilidades de seguridad que se integran con OpenAPI (y la documentación automática de la API) heredan de `SecurityBase`, así es como **FastAPI** puede saber cómo integrarlas en OpenAPI.
///
@@ -4,7 +4,9 @@ En el capítulo anterior, el sistema de seguridad (que se basa en el sistema de
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
Pero eso aún no es tan útil. Vamos a hacer que nos dé el usuario actual.
Pero eso aún no es tan útil.
Vamos a hacer que nos dé el usuario actual.
## Crear un modelo de usuario { #create-a-user-model }
@@ -12,7 +14,7 @@ Primero, vamos a crear un modelo de usuario con Pydantic.
De la misma manera que usamos Pydantic para declarar cuerpos, podemos usarlo en cualquier otra parte:
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *}
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *}
## Crear una dependencia `get_current_user` { #create-a-get-current-user-dependency }
@@ -50,7 +52,7 @@ Aquí **FastAPI** no se confundirá porque estás usando `Depends`.
///
/// check | Revisa
/// tip | Consejo
El modo en que este sistema de dependencias está diseñado nos permite tener diferentes dependencias (diferentes "dependables") que todas devuelven un modelo `User`.
@@ -66,7 +68,7 @@ Y puedes usar cualquier modelo o datos para los requisitos de seguridad (en este
Pero no estás limitado a usar algún modelo de datos, clase o tipo específico.
¿Quieres tener un `id` y `email` y no tener un `username` en tu modelo? Claro. Puedes usar estas mismas herramientas.
¿Quieres tener un `id` y `email` y no tener ningún `username` en tu modelo? Claro. Puedes usar estas mismas herramientas.
¿Quieres solo tener un `str`? ¿O solo un `dict`? ¿O un instance de clase modelo de base de datos directamente? Todo funciona de la misma manera.
+3 -2
View File
@@ -1,5 +1,6 @@
# OAuth2 con Password (y hashing), Bearer con tokens JWT { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens }
Ahora que tenemos todo el flujo de seguridad, hagamos que la aplicación sea realmente segura, usando tokens <abbr title="JSON Web Tokens">JWT</abbr> y hashing de contraseñas seguras.
Este código es algo que puedes usar realmente en tu aplicación, guardar los hashes de las contraseñas en tu base de datos, etc.
@@ -42,7 +43,7 @@ $ pip install pyjwt
</div>
/// info | Información
/// note | Nota
Si planeas usar algoritmos de firma digital como RSA o ECDSA, deberías instalar la dependencia del paquete de criptografía `pyjwt[crypto]`.
@@ -213,7 +214,7 @@ Usando las credenciales:
Usuario: `johndoe`
Contraseña: `secret`
/// check | Revisa
/// tip | Consejo
Observa que en ninguna parte del código está la contraseña en texto claro "`secret`", solo tenemos la versión con hash.
@@ -32,7 +32,7 @@ Normalmente se utilizan para declarar permisos de seguridad específicos, por ej
* `instagram_basic` es usado por Facebook / Instagram.
* `https://www.googleapis.com/auth/drive` es usado por Google.
/// info | Información
/// note | Nota
En OAuth2 un "scope" es solo un string que declara un permiso específico requerido.
@@ -72,7 +72,7 @@ Si necesitas imponerlo, utiliza `OAuth2PasswordRequestFormStrict` en lugar de `O
* Un `client_id` opcional (no lo necesitamos para nuestro ejemplo).
* Un `client_secret` opcional (no lo necesitamos para nuestro ejemplo).
/// info | Información
/// note | Nota
`OAuth2PasswordRequestForm` no es una clase especial para **FastAPI** como lo es `OAuth2PasswordBearer`.
@@ -94,7 +94,7 @@ No estamos usando `scopes` en este ejemplo, pero la funcionalidad está ahí si
///
Ahora, obtén los datos del usuario desde la base de datos (falsa), usando el `username` del campo del form.
Ahora, obtén los datos del usuario desde la base de datos (falsa), usando el `username` del campo del formulario.
Si no existe tal usuario, devolvemos un error diciendo "Incorrect username or password".
@@ -144,9 +144,9 @@ UserInDB(
)
```
/// info | Información
/// note | Nota
Para una explicación más completa de `**user_dict` revisa en [la documentación para **Extra Models**](../extra-models.md#about-user-in-dict).
Para una explicación más completa de `**user_dict` revisa en [la documentación para **Extra Models**](../extra-models.md#about-user-in-model-dump).
///
@@ -196,7 +196,7 @@ Así que, en nuestro endpoint, solo obtendremos un usuario si el usuario existe,
{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *}
/// info | Información
/// note | Nota
El header adicional `WWW-Authenticate` con el valor `Bearer` que estamos devolviendo aquí también es parte de la especificación.
+1 -1
View File
@@ -4,7 +4,7 @@ Puedes enviar datos en streaming al cliente usando **Server-Sent Events** (SSE).
Esto es similar a [Stream JSON Lines](stream-json-lines.md), pero usa el formato `text/event-stream`, que los navegadores soportan de forma nativa con la [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource).
/// info | Información
/// note | Nota
Añadido en FastAPI 0.135.0.
+3 -3
View File
@@ -65,7 +65,7 @@ Hay algunas diferencias:
* `Field(primary_key=True)` le dice a SQLModel que `id` es la **clave primaria** en la base de datos SQL (puedes aprender más sobre claves primarias de SQL en la documentación de SQLModel).
Nota: Usamos `int | None` para el campo de clave primaria para que en el código Python podamos *crear un objeto sin un `id`* (`id=None`), asumiendo que la base de datos lo *generará al guardar*. SQLModel entiende que la base de datos proporcionará el `id` y *define la columna como un `INTEGER` no nulo* en el esquema de la base de datos. Consulta la [documentación de SQLModel sobre claves primarias](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) para más detalles.
**Nota:** Usamos `int | None` para el campo de clave primaria para que en el código Python podamos *crear un objeto sin un `id`* (`id=None`), asumiendo que la base de datos lo *generará al guardar*. SQLModel entiende que la base de datos proporcionará el `id` y *define la columna como un `INTEGER` no nulo* en el esquema de la base de datos. Consulta la [documentación de SQLModel sobre claves primarias](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id) para más detalles.
* `Field(index=True)` le dice a SQLModel que debe crear un **índice SQL** para esta columna, lo que permitirá búsquedas más rápidas en la base de datos cuando se lean datos filtrados por esta columna.
@@ -181,7 +181,7 @@ Arreglaremos estas cosas añadiendo unos **modelos extra**. Aquí es donde SQLMo
En **SQLModel**, cualquier clase de modelo que tenga `table=True` es un **modelo de tabla**.
Y cualquier clase de modelo que no tenga `table=True` es un **modelo de datos**, estos son en realidad solo modelos de Pydantic (con un par de características extra pequeñas). 🤓
Y cualquier clase de modelo que no tenga `table=True` es un **modelo de datos**, estos son en realidad solo modelos de Pydantic (con un par de pequeñas funcionalidades extra). 🤓
Con SQLModel, podemos usar **herencia** para **evitar duplicar** todos los campos en todos los casos.
@@ -296,7 +296,7 @@ Ahora usamos `response_model=HeroPublic` en lugar de la **anotación de tipo de
Si hubiéramos declarado `-> HeroPublic`, tu editor y linter se quejarían (con razón) de que estás devolviendo un `Hero` en lugar de un `HeroPublic`.
Al declararlo en `response_model` le estamos diciendo a **FastAPI** que haga lo suyo, sin interferir con las anotaciones de tipo y la ayuda de tu editor y otras herramientas.
Al declararlo en `response_model` le estamos diciendo a **FastAPI** que haga lo suyo, sin interferir con las anotaciones de tipos y la ayuda de tu editor y otras herramientas.
///
+8
View File
@@ -2,6 +2,14 @@
Puedes servir archivos estáticos automáticamente desde un directorio utilizando `StaticFiles`.
/// tip | Consejo
Si necesitas alojar un frontend, usa `app.frontend()` en su lugar, lee sobre ello en [Frontend](frontend.md).
`app.frontend()` usa `StaticFiles` por debajo, con varias ventajas adicionales para frontends, como manejar el routing del lado del cliente.
///
## Usa `StaticFiles` { #use-staticfiles }
* Importa `StaticFiles`.
+2 -2
View File
@@ -2,7 +2,7 @@
Podrías tener una secuencia de datos que quieras enviar en un "**stream**", podrías hacerlo con **JSON Lines**.
/// info | Información
/// note | Nota
Añadido en FastAPI 0.134.0.
@@ -48,7 +48,7 @@ Una response tendría un tipo de contenido `application/jsonl` (en lugar de `app
Es muy similar a un array JSON (equivalente de una list de Python), pero en lugar de estar envuelto en `[]` y tener `,` entre los ítems, tiene **un objeto JSON por línea**, separados por un carácter de nueva línea.
/// info | Información
/// note | Nota
El punto importante es que tu app podrá producir cada línea a su turno, mientras el cliente consume las líneas anteriores.
+5 -5
View File
@@ -1,4 +1,4 @@
# Testing { #testing }
# Pruebas { #testing }
Gracias a [Starlette](https://www.starlette.dev/testclient/), escribir pruebas para aplicaciones de **FastAPI** es fácil y agradable.
@@ -8,7 +8,7 @@ Con él, puedes usar [pytest](https://docs.pytest.org/) directamente con **FastA
## Usando `TestClient` { #using-testclient }
/// info | Información
/// note | Nota
Para usar `TestClient`, primero instala [`httpx`](https://www.python-httpx.org).
@@ -28,7 +28,7 @@ Crea funciones con un nombre que comience con `test_` (esta es la convención es
Usa el objeto `TestClient` de la misma manera que con `httpx`.
Escribe declaraciones `assert` simples con las expresiones estándar de Python que necesites revisar (otra vez, estándar de `pytest`).
Escribe statements `assert` simples con las expresiones estándar de Python que necesites revisar (otra vez, estándar de `pytest`).
{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *}
@@ -90,7 +90,7 @@ Entonces podrías tener un archivo `test_main.py` con tus pruebas. Podría estar
│   └── test_main.py
```
Debido a que este archivo está en el mismo paquete, puedes usar importaciones relativas para importar el objeto `app` desde el módulo `main` (`main.py`):
Debido a que este archivo está en el mismo paquete, puedes usar imports relativos para importar el objeto `app` desde el módulo `main` (`main.py`):
{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *}
@@ -142,7 +142,7 @@ Por ejemplo:
Para más información sobre cómo pasar datos al backend (usando `httpx` o el `TestClient`) revisa la [documentación de HTTPX](https://www.python-httpx.org).
/// info | Información
/// note | Nota
Ten en cuenta que el `TestClient` recibe datos que pueden ser convertidos a JSON, no modelos de Pydantic.
+7 -5
View File
@@ -288,8 +288,8 @@ $ echo "*" > .venv/.gitignore
/// details | Qué significa ese comando
* `echo "*"`: "imprimirá" el texto `*` en el terminal (la siguiente parte cambia eso un poco)
* `>`: cualquier cosa impresa en el terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>`
* `echo "*"`: "imprimirá" el texto `*` en la terminal (la siguiente parte cambia eso un poco)
* `>`: cualquier cosa impresa en la terminal por el comando a la izquierda de `>` no debería imprimirse, sino escribirse en el archivo que va a la derecha de `>`
* `.gitignore`: el nombre del archivo donde debería escribirse el texto
Y `*` para Git significa "todo". Así que, ignorará todo en el directorio `.venv`.
@@ -443,6 +443,8 @@ De esta manera, cuando ejecutes `python` no intentará ejecutarse desde ese ento
Ahora estás listo para empezar a trabajar en tu proyecto.
/// tip | Consejo
¿Quieres entender todo lo anterior?
@@ -694,7 +696,7 @@ Eso significa que el sistema ahora comenzará a buscar primero los programas en:
antes de buscar en los otros directorios.
Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en
Así que, cuando escribas `python` en la terminal, el sistema encontrará el programa Python en
```plaintext
/home/user/code/awesome-project/.venv/bin/python
@@ -718,7 +720,7 @@ C:\Users\user\code\awesome-project\.venv\Scripts
antes de buscar en los otros directorios.
Así que, cuando escribas `python` en el terminal, el sistema encontrará el programa Python en
Así que, cuando escribas `python` en la terminal, el sistema encontrará el programa Python en
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts\python
@@ -800,7 +802,7 @@ $ cd ~/code/prisoner-of-azkaban
</div>
Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en el terminal, intentará usar el Python de `philosophers-stone`.
Si no desactivas el entorno virtual para `philosophers-stone`, cuando ejecutes `python` en la terminal, intentará usar el Python de `philosophers-stone`.
<div class="termy">