///
-/// info | Información
+/// note | Nota
La clave `model` no es parte de OpenAPI.
///
-/// 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`).
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.
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 }
{* ../../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.
///
-/// 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.
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.
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.
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.
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/).
## 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.
+Esta sección destaca soluciones **respaldadas por empresas** y **venture-backed** de compañías que sponsor 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**.
+Al ✨ [**ser sponsor de 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. 🤓
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 }
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.
///
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.
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.
### 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
## 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`.
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.
* `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.
{* ../../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.
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.
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.
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.
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 }
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.
{* ../../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`.
## Usando `WSGIMiddleware` { #using-wsgimiddleware }
-/// info | Información
+/// note | Nota
Esto requiere instalar `a2wsgi`, por ejemplo con `pip install a2wsgi`.
</div>
-/// info | Información
+/// note | Nota
Existen otros formatos y herramientas para definir e instalar dependencias de paquetes.
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/).
# 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">
</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 }
* [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 }
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).
* `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.
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`. 🤓
* **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, 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.
### 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">
</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 }
/// 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.
///
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. ⚡
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.
///
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.
+
+///
{* ../../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.
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:
}
```
-/// info | Información
+/// note | Nota
Nota cómo la clave `images` ahora tiene una lista de objetos de imagen.
{* ../../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
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`.
<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.
///
-/// 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.
# 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:
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).
* 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.
///
-/// info | Información
+/// note | Nota
En este ejemplo usamos headers personalizados inventados `X-Key` y `X-Token`.
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*.
# 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.
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.
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.
{* ../../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`.
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:
$ fastapi dev main.py
```
-Pero tendrías que recordar pasar el path 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">
+O, también puedes pasar la opción `--entrypoint` al comando `fastapi dev`:
```console
-$ fastapi login
-
-You are logged in to FastAPI Cloud 🚀
+$ fastapi dev --entrypoint main:app
```
-</div>
+Pero tendrías que recordar pasar el path o entrypoint correctos 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`.
-Luego despliega tu app:
+### Despliega tu app (opcional) { #deploy-your-app-optional }
+
+Opcionalmente puedes desplegar tu app de FastAPI en [FastAPI Cloud](https://fastapicloud.com) con un solo comando. 🚀
<div class="termy">
</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 }
/items/foo
```
-/// info | Información
+/// note | Nota
Un "path" también es comúnmente llamado "endpoint" o "ruta".
* 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".
{* ../../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).
{* ../../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.
{* ../../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.
* `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`.
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.
{"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"`.
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.
<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).
## 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 }
{* ../../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.
Ten en cuenta que en este caso, FastAPI no comprobará 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]` comprobaría (and documentaría) que el contenido de la list son enteros. Pero `list` sola no lo haría.
///
{* ../../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. 😎
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.
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).
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
-/// info | Información
+/// note | Nota
`File` es una clase que hereda directamente de `Form`.
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).
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).
-# 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).
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`.
## 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.
{* ../../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).
}
```
-/// info | Información
+/// note | Nota
También puedes usar:
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.
///
-/// 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**.
* `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`.
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 🎉).
## 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]"`.
<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".
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.
Pronto también crearemos la verdadera *path operation*.
-/// 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`.
**FastAPI** sabrá que puede usar esta dependencia para definir un "security scheme" en el esquema OpenAPI (y en los docs automáticos del 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`.
///
-/// 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`.
</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]`.
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.
* `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.
* 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`.
///
-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".
)
```
-/// 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).
{* ../../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.
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.
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.
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.
-# Testing { #testing }
+# Pruebas { #testing }
Gracias a [Starlette](https://www.starlette.dev/testclient/), escribir pruebas para aplicaciones de **FastAPI** es fácil y agradable.
## Usando `TestClient` { #using-testclient }
-/// info | Información
+/// note | Nota
Para usar `TestClient`, primero instala [`httpx`](https://www.python-httpx.org).
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.