Y el proxy estaría **"eliminando"** el **prefijo del path** sobre la marcha antes de transmitir el request al servidor de aplicaciones (probablemente Uvicorn a través de FastAPI CLI), manteniendo a tu aplicación convencida de que está siendo servida en `/app`, así que no tienes que actualizar todo tu código para incluir el prefijo `/api/v1`.
@ -193,7 +193,7 @@ Puedes obtener el `root_path` actual utilizado por tu aplicación para cada requ
Aquí lo estamos incluyendo en el mensaje solo con fines de demostración.
Alternativamente, si no tienes una forma de proporcionar una opción de línea de comandos como `--root-path` o su equivalente, puedes configurar el parámetro `root_path` al crear tu app de FastAPI:
@ -30,7 +30,7 @@ Esto se debe a que, por defecto, FastAPI inspeccionará cada elemento dentro y s
Pero si estás seguro de que el contenido que estás devolviendo es **serializable con JSON**, puedes pasarlo directamente a la clase de response y evitar la sobrecarga extra que FastAPI tendría al pasar tu contenido de retorno a través de `jsonable_encoder` antes de pasarlo a la clase de response.
En este ejemplo, la función `generate_html_response()` ya genera y devuelve una `Response` en lugar de devolver el HTML en un `str`.
@ -136,7 +136,7 @@ Acepta los siguientes parámetros:
FastAPI (de hecho Starlette) incluirá automáticamente un header Content-Length. También incluirá un header Content-Type, basado en el `media_type` y añadiendo un conjunto de caracteres para tipos de texto.
1. Esta es la función generadora. Es una "función generadora" porque contiene declaraciones `yield` dentro.
2. Al usar un bloque `with`, nos aseguramos de que el objeto similar a un archivo se cierre después de que la función generadora termine. Así, después de que termina de enviar el response.
@ -255,11 +255,11 @@ Toma un conjunto diferente de argumentos para crear un instance que los otros ti
Los responses de archivos incluirán los headers apropiados `Content-Length`, `Last-Modified` y `ETag`.
En este caso, puedes devolver la path del archivo directamente desde tu *path operation* function.
@ -273,7 +273,7 @@ Digamos que quieres que devuelva JSON con sangría y formato, por lo que quieres
Podrías crear un `CustomORJSONResponse`. Lo principal que tienes que hacer es crear un método `Response.render(content)` que devuelva el contenido como `bytes`:
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*.
@ -48,7 +48,7 @@ Quizás necesites iniciar una nueva versión, o simplemente te cansaste de ejecu
Lo primero que hay que notar es que estamos definiendo una función asíncrona con `yield`. Esto es muy similar a las Dependencias con `yield`.
Un **context manager** en Python es algo que puedes usar en un statement `with`, por ejemplo, `open()` puede ser usado como un context manager:
@ -82,7 +82,7 @@ En nuestro ejemplo de código arriba, no lo usamos directamente, pero se lo pasa
El parámetro `lifespan` de la app de `FastAPI` toma un **async context manager**, por lo que podemos pasar nuestro nuevo `lifespan` async context manager a él.
@ -32,7 +32,7 @@ Los webhooks están disponibles en OpenAPI 3.1.0 y superiores, soportados por Fa
Cuando creas una aplicación de **FastAPI**, hay un atributo `webhooks` que puedes usar para definir *webhooks*, de la misma manera que definirías *path operations*, por ejemplo con `@app.webhooks.post()`.
@ -40,7 +40,7 @@ Incluso si están en diferentes módulos (archivos de Python).
Para excluir una *path operation* del esquema OpenAPI generado (y por lo tanto, de los sistemas de documentación automática), utiliza el parámetro `include_in_schema` y configúralo en `False`:
## Descripción avanzada desde el docstring { #advanced-description-from-docstring }
@ -92,7 +92,7 @@ Puedes extender el esquema de OpenAPI para una *path operation* usando el parám
Este `openapi_extra` puede ser útil, por ejemplo, para declarar [Extensiones de OpenAPI](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions):
En este ejemplo, no declaramos ningún modelo Pydantic. De hecho, el cuerpo del request ni siquiera se <abbrtitle="convertido de algún formato plano, como bytes, a objetos de Python">parse</abbr> como JSON, se lee directamente como `bytes`, y la función `magic_data_reader()` sería la encargada de parsearlo de alguna manera.
Y luego puedes devolver cualquier objeto que necesites, como harías normalmente (un `dict`, un modelo de base de datos, etc).
@ -22,7 +22,7 @@ También puedes agregar headers cuando devuelves un `Response` directamente.
Crea un response como se describe en [Retorna un Response Directamente](response-directly.md){.internal-link target=_blank} y pasa los headers como un parámetro adicional:
* Declara un parámetro `Request` en la *path operation* que devolverá una plantilla.
* Usa los `templates` que creaste para renderizar y devolver un `TemplateResponse`, pasa el nombre de la plantilla, el objeto de request, y un diccionario "context" con pares clave-valor que se usarán dentro de la plantilla Jinja2.
Puedes leer más detalles sobre ["Ejecutar lifespan en tests en el sitio oficial de documentación de Starlette."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests)
Para los eventos obsoletos `startup` y `shutdown`, puedes usar el `TestClient` así:
...y entonces Swagger UI ya no mostrará el resaltado de sintaxis:
@ -28,7 +28,7 @@ Pero puedes desactivarlo estableciendo `syntaxHighlight` en `False`:
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):
Usar `Optional[str]` en lugar de solo `str` te permitirá al editor ayudarte a detectar errores donde podrías estar asumiendo que un valor siempre es un `str`, cuando en realidad también podría ser `None`.
@ -326,18 +266,18 @@ Esto también significa que en Python 3.10, puedes usar `Something | None`:
El parámetro `name` está definido como `Optional[str]`, pero **no es opcional**, no puedes llamar a la función sin el parámetro:
@ -390,10 +330,10 @@ Puedes usar los mismos tipos integrados como genéricos (con corchetes y tipos d
* `set`
* `dict`
Y lo mismo que con Python 3.8, desde el módulo `typing`:
Y, como con versiones anteriores de Python, desde el módulo `typing`:
* `Union`
* `Optional` (lo mismo que con Python 3.8)
* `Optional`
* ...y otros.
En Python 3.10, como alternativa a usar los genéricos `Union` y `Optional`, puedes usar la <abbrtitle='también llamado "operador OR a nivel de bits", pero ese significado no es relevante aquí'>barra vertical (`|`)</abbr> para declarar uniones de tipos, eso es mucho mejor y más simple.
@ -409,7 +349,7 @@ Puedes usar los mismos tipos integrados como genéricos (con corchetes y tipos d
* `set`
* `dict`
Y lo mismo que con Python 3.8, desde el módulo `typing`:
Y generics desde el módulo `typing`:
* `Union`
* `Optional`
@ -417,29 +357,17 @@ Y lo mismo que con Python 3.8, desde el módulo `typing`:
////
//// tab | Python 3.8+
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Union`
* `Optional`
* ...y otros.
////
### Clases como tipos { #classes-as-types }
También puedes declarar una clase como el tipo de una variable.
Digamos que tienes una clase `Person`, con un nombre:
@ -507,27 +413,9 @@ Pydantic tiene un comportamiento especial cuando utilizas `Optional` o `Union[So
Python también tiene una funcionalidad que permite poner **<abbrtitle="Datos sobre los datos, en este caso, información sobre el tipo, por ejemplo, una descripción.">metadatos</abbr> adicional** en estas anotaciones de tipos usando `Annotated`.
//// tab | Python 3.9+
En Python 3.9, `Annotated` es parte de la standard library, así que puedes importarlo desde `typing`.
Desde Python 3.9, `Annotated` es parte de la standard library, así que puedes importarlo desde `typing`.
### Declarar una `list` con un parámetro de tipo { #declare-a-list-with-a-type-parameter }
Para declarar tipos que tienen parámetros de tipo (tipos internos), como `list`, `dict`, `tuple`:
* Si estás en una versión de Python inferior a 3.9, importa su versión equivalente del módulo `typing`
* Pasa el/los tipo(s) interno(s) como "parámetros de tipo" usando corchetes: `[` y `]`
En Python 3.9 sería:
Para declarar tipos que tienen parámetros de tipo (tipos internos), como `list`, `dict`, `tuple`,
pasa el/los tipo(s) interno(s) como "parámetros de tipo" usando corchetes: `[` y `]`
```Python
my_list: list[str]
```
En versiones de Python anteriores a 3.9, sería:
```Python
from typing import List
my_list: List[str]
```
Eso es toda la sintaxis estándar de Python para declaraciones de tipo.
Usa esa misma sintaxis estándar para atributos de modelos con tipos internos.
@ -178,12 +158,6 @@ Observa cómo `Offer` tiene una lista de `Item`s, que a su vez tienen una lista
Si el valor superior del cuerpo JSON que esperas es un `array` JSON (una `list` en Python), puedes declarar el tipo en el parámetro de la función, al igual que en los modelos Pydantic:
Los parámetros predeterminados utilizados por la implementación de `CORSMiddleware` son restrictivos por defecto, por lo que necesitarás habilitar explícitamente orígenes, métodos o headers particulares para que los navegadores estén permitidos de usarlos en un contexto de Cross-Domain.
Y todas las ideas en la sección sobre [agregar `dependencies` a los *path operation decorators*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} siguen aplicándose, pero en este caso, a todas las *path operations* en la app.
@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
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`:
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.
Nota que puedes utilizar Markdown dentro de las descripciones, por ejemplo "login" se mostrará en negrita (**login**) y "fancy" se mostrará en cursiva (_fancy_).
@ -72,7 +72,7 @@ No tienes que agregar metadata para todas las etiquetas que uses.
Usa el parámetro `tags` con tus *path operations* (y `APIRouter`s) para asignarlas a diferentes etiquetas:
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.
@ -117,4 +117,4 @@ Puedes configurar las dos interfaces de usuario de documentación incluidas:
Por ejemplo, para configurar Swagger UI para que se sirva en `/documentation` y deshabilitar ReDoc:
## Resumen y Descripción { #summary-and-description }
@ -92,7 +92,7 @@ Entonces, si no proporcionas una, **FastAPI** generará automáticamente una de
Si necesitas marcar una *path operation* como <abbrtitle="obsoleta, se recomienda no usarla">deprecated</abbr>, pero sin eliminarla, pasa el parámetro `deprecated`:
Pero ten en cuenta que si usas `Annotated`, no tendrás este problema, no importará ya que no estás usando los valores por defecto de los parámetros de la función para `Query()` o `Path()`.
@ -83,7 +83,7 @@ Pasa `*`, como el primer parámetro de la función.
Python no hará nada con ese `*`, pero sabrá que todos los parámetros siguientes deben ser llamados como argumentos de palabras clave (parejas key-value), también conocidos como <abbrtitle="De: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>. Incluso si no tienen un valor por defecto.
@ -118,13 +118,13 @@ Y luego también puedes tener un path `/users/{user_id}` para obtener datos sobr
Debido a que las *path operations* se evalúan en orden, necesitas asegurarte de que el path para `/users/me` se declara antes que el de `/users/{user_id}`:
De lo contrario, el path para `/users/{user_id}` también coincidiría para `/users/me`, "pensando" que está recibiendo un parámetro `user_id` con un valor de `"me"`.
De manera similar, no puedes redefinir una path operation:
<ahref="https://docs.python.org/3/library/enum.html"class="external-link"target="_blank">Las enumeraciones (o enums) están disponibles en Python</a> desde la versión 3.4.
@ -183,7 +183,7 @@ Podría haber casos en los que devuelvas algo que no es un campo válido de Pyda
El caso más común sería [devolver un Response directamente como se explica más adelante en la documentación avanzada](../advanced/response-directly.md){.internal-link target=_blank}.
@ -91,7 +91,7 @@ Entonces podrías tener un archivo `test_main.py` con tus pruebas. Podría estar
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`):