Browse Source
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>pull/14687/head
committed by
GitHub
13 changed files with 117 additions and 270 deletions
@ -46,12 +46,6 @@ $ pip install "fastapi[all]" |
|||
|
|||
</div> |
|||
|
|||
/// info | Información |
|||
|
|||
En Pydantic v1 venía incluido con el paquete principal. Ahora se distribuye como este paquete independiente para que puedas elegir si instalarlo o no si no necesitas esa funcionalidad. |
|||
|
|||
/// |
|||
|
|||
### Crear el objeto `Settings` { #create-the-settings-object } |
|||
|
|||
Importa `BaseSettings` de Pydantic y crea una sub-clase, muy similar a un modelo de Pydantic. |
|||
@ -60,31 +54,15 @@ De la misma forma que con los modelos de Pydantic, declaras atributos de clase c |
|||
|
|||
Puedes usar todas las mismas funcionalidades de validación y herramientas que usas para los modelos de Pydantic, como diferentes tipos de datos y validaciones adicionales con `Field()`. |
|||
|
|||
//// tab | Pydantic v2 |
|||
|
|||
{* ../../docs_src/settings/tutorial001_py39.py hl[2,5:8,11] *} |
|||
|
|||
//// |
|||
|
|||
//// tab | Pydantic v1 |
|||
|
|||
/// info | Información |
|||
|
|||
En Pydantic v1 importarías `BaseSettings` directamente desde `pydantic` en lugar de desde `pydantic_settings`. |
|||
|
|||
/// |
|||
|
|||
{* ../../docs_src/settings/tutorial001_pv1_py39.py hl[2,5:8,11] *} |
|||
|
|||
//// |
|||
|
|||
/// tip | Consejo |
|||
|
|||
Si quieres algo rápido para copiar y pegar, no uses este ejemplo, usa el último más abajo. |
|||
|
|||
/// |
|||
|
|||
Luego, cuando creas una instance de esa clase `Settings` (en este caso, en el objeto `settings`), Pydantic leerá las variables de entorno de una manera indiferente a mayúsculas y minúsculas, por lo que una variable en mayúsculas `APP_NAME` aún será leída para el atributo `app_name`. |
|||
Luego, cuando creas un instance de esa clase `Settings` (en este caso, en el objeto `settings`), Pydantic leerá las variables de entorno de una manera indiferente a mayúsculas y minúsculas, por lo que una variable en mayúsculas `APP_NAME` aún será leída para el atributo `app_name`. |
|||
|
|||
Luego convertirá y validará los datos. Así que, cuando uses ese objeto `settings`, tendrás datos de los tipos que declaraste (por ejemplo, `items_per_user` será un `int`). |
|||
|
|||
@ -110,7 +88,7 @@ $ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.p |
|||
|
|||
/// tip | Consejo |
|||
|
|||
Para establecer múltiples variables de entorno para un solo comando, simplemente sepáralas con un espacio y ponlas todas antes del comando. |
|||
Para establecer múltiples env vars para un solo comando, simplemente sepáralas con un espacio y ponlas todas antes del comando. |
|||
|
|||
/// |
|||
|
|||
@ -150,7 +128,7 @@ Proveniente del ejemplo anterior, tu archivo `config.py` podría verse como: |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/config.py hl[10] *} |
|||
|
|||
Nota que ahora no creamos una instance por defecto `settings = Settings()`. |
|||
Nota que ahora no creamos un instance por defecto `settings = Settings()`. |
|||
|
|||
### El archivo principal de la app { #the-main-app-file } |
|||
|
|||
@ -172,11 +150,11 @@ Y luego podemos requerirlo desde la *path operation function* como una dependenc |
|||
|
|||
### Configuraciones y pruebas { #settings-and-testing } |
|||
|
|||
Luego sería muy fácil proporcionar un objeto de configuraciones diferente durante las pruebas al sobrescribir una dependencia para `get_settings`: |
|||
Luego sería muy fácil proporcionar un objeto de configuraciones diferente durante las pruebas al crear una sobrescritura de dependencia para `get_settings`: |
|||
|
|||
{* ../../docs_src/settings/app02_an_py39/test_main.py hl[9:10,13,21] *} |
|||
|
|||
En la dependencia sobreescrita establecemos un nuevo valor para el `admin_email` al crear el nuevo objeto `Settings`, y luego devolvemos ese nuevo objeto. |
|||
En la sobrescritura de dependencia establecemos un nuevo valor para el `admin_email` al crear el nuevo objeto `Settings`, y luego devolvemos ese nuevo objeto. |
|||
|
|||
Luego podemos probar que se está usando. |
|||
|
|||
@ -215,8 +193,6 @@ APP_NAME="ChimichangApp" |
|||
|
|||
Y luego actualizar tu `config.py` con: |
|||
|
|||
//// tab | Pydantic v2 |
|||
|
|||
{* ../../docs_src/settings/app03_an_py39/config.py hl[9] *} |
|||
|
|||
/// tip | Consejo |
|||
@ -225,26 +201,6 @@ El atributo `model_config` se usa solo para configuración de Pydantic. Puedes l |
|||
|
|||
/// |
|||
|
|||
//// |
|||
|
|||
//// tab | Pydantic v1 |
|||
|
|||
{* ../../docs_src/settings/app03_an_py39/config_pv1.py hl[9:10] *} |
|||
|
|||
/// tip | Consejo |
|||
|
|||
La clase `Config` se usa solo para configuración de Pydantic. Puedes leer más en <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>. |
|||
|
|||
/// |
|||
|
|||
//// |
|||
|
|||
/// info | Información |
|||
|
|||
En la versión 1 de Pydantic la configuración se hacía en una clase interna `Config`, en la versión 2 de Pydantic se hace en un atributo `model_config`. Este atributo toma un `dict`, y para obtener autocompletado y errores en línea, puedes importar y usar `SettingsConfigDict` para definir ese `dict`. |
|||
|
|||
/// |
|||
|
|||
Aquí definimos la configuración `env_file` dentro de tu clase Pydantic `Settings`, y establecemos el valor en el nombre del archivo con el archivo dotenv que queremos usar. |
|||
|
|||
### Creando el `Settings` solo una vez con `lru_cache` { #creating-the-settings-only-once-with-lru-cache } |
|||
@ -331,7 +287,7 @@ participant execute as Ejecutar función |
|||
end |
|||
``` |
|||
|
|||
En el caso de nuestra dependencia `get_settings()`, la función ni siquiera toma argumentos, por lo que siempre devolverá el mismo valor. |
|||
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. |
|||
|
|||
|
|||
@ -22,21 +22,13 @@ Aquí tienes una idea general de cómo podrían ser los modelos con sus campos d |
|||
|
|||
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} |
|||
|
|||
/// info | Información |
|||
### Acerca de `**user_in.model_dump()` { #about-user-in-model-dump } |
|||
|
|||
En Pydantic v1 el método se llamaba `.dict()`, fue deprecado (pero aún soportado) en Pydantic v2, y renombrado a `.model_dump()`. |
|||
|
|||
Los ejemplos aquí usan `.dict()` para compatibilidad con Pydantic v1, pero deberías usar `.model_dump()` en su lugar si puedes usar Pydantic v2. |
|||
|
|||
/// |
|||
|
|||
### Acerca de `**user_in.dict()` { #about-user-in-dict } |
|||
|
|||
#### `.dict()` de Pydantic { #pydantics-dict } |
|||
#### `.model_dump()` de Pydantic { #pydantics-model-dump } |
|||
|
|||
`user_in` es un modelo Pydantic de la clase `UserIn`. |
|||
|
|||
Los modelos Pydantic tienen un método `.dict()` que devuelve un `dict` con los datos del modelo. |
|||
Los modelos Pydantic tienen un método `.model_dump()` que devuelve un `dict` con los datos del modelo. |
|||
|
|||
Así que, si creamos un objeto Pydantic `user_in` como: |
|||
|
|||
@ -47,7 +39,7 @@ user_in = UserIn(username="john", password="secret", email="[email protected] |
|||
y luego llamamos a: |
|||
|
|||
```Python |
|||
user_dict = user_in.dict() |
|||
user_dict = user_in.model_dump() |
|||
``` |
|||
|
|||
ahora tenemos un `dict` con los datos en la variable `user_dict` (es un `dict` en lugar de un objeto modelo Pydantic). |
|||
@ -58,7 +50,7 @@ Y si llamamos a: |
|||
print(user_dict) |
|||
``` |
|||
|
|||
obtendremos un `dict` de Python con: |
|||
obtendríamos un `dict` de Python con: |
|||
|
|||
```Python |
|||
{ |
|||
@ -103,20 +95,20 @@ UserInDB( |
|||
|
|||
#### Un modelo Pydantic a partir del contenido de otro { #a-pydantic-model-from-the-contents-of-another } |
|||
|
|||
Como en el ejemplo anterior obtuvimos `user_dict` de `user_in.dict()`, este código: |
|||
Como en el ejemplo anterior obtuvimos `user_dict` de `user_in.model_dump()`, este código: |
|||
|
|||
```Python |
|||
user_dict = user_in.dict() |
|||
user_dict = user_in.model_dump() |
|||
UserInDB(**user_dict) |
|||
``` |
|||
|
|||
sería equivalente a: |
|||
|
|||
```Python |
|||
UserInDB(**user_in.dict()) |
|||
UserInDB(**user_in.model_dump()) |
|||
``` |
|||
|
|||
...porque `user_in.dict()` es un `dict`, y luego hacemos que Python lo "desempaquete" al pasarlo a `UserInDB` con el prefijo `**`. |
|||
...porque `user_in.model_dump()` es un `dict`, y luego hacemos que Python lo "desempaquete" al pasarlo a `UserInDB` con el prefijo `**`. |
|||
|
|||
Así, obtenemos un modelo Pydantic a partir de los datos en otro modelo Pydantic. |
|||
|
|||
@ -125,7 +117,7 @@ Así, obtenemos un modelo Pydantic a partir de los datos en otro modelo Pydantic |
|||
Y luego agregando el argumento de palabra clave adicional `hashed_password=hashed_password`, como en: |
|||
|
|||
```Python |
|||
UserInDB(**user_in.dict(), hashed_password=hashed_password) |
|||
UserInDB(**user_in.model_dump(), hashed_password=hashed_password) |
|||
``` |
|||
|
|||
...termina siendo como: |
|||
@ -156,7 +148,7 @@ Y estos modelos están compartiendo muchos de los datos y duplicando nombres y t |
|||
|
|||
Podríamos hacerlo mejor. |
|||
|
|||
Podemos declarar un modelo `UserBase` que sirva como base para nuestros otros modelos. Y luego podemos hacer subclases de ese modelo que heredan sus atributos (anotaciones de tipos, validación, etc). |
|||
Podemos declarar un modelo `UserBase` que sirva como base para nuestros otros modelos. Y luego podemos hacer subclases de ese modelo que heredan sus atributos (declaraciones de tipos, validación, etc). |
|||
|
|||
Toda la conversión de datos, validación, documentación, etc. seguirá funcionando normalmente. |
|||
|
|||
@ -180,20 +172,19 @@ Al definir una <a href="https://docs.pydantic.dev/latest/concepts/types/#unions" |
|||
|
|||
{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} |
|||
|
|||
|
|||
### `Union` en Python 3.10 { #union-in-python-3-10 } |
|||
|
|||
En este ejemplo pasamos `Union[PlaneItem, CarItem]` como el valor del argumento `response_model`. |
|||
|
|||
Porque lo estamos pasando como un **valor a un argumento** en lugar de ponerlo en **anotaciones de tipos**, tenemos que usar `Union` incluso en Python 3.10. |
|||
Porque lo estamos pasando como un **valor a un argumento** en lugar de ponerlo en una **anotación de tipos**, tenemos que usar `Union` incluso en Python 3.10. |
|||
|
|||
Si estuviera en anotaciones de tipos podríamos haber usado la barra vertical, como: |
|||
Si estuviera en una anotación de tipos podríamos haber usado la barra vertical, como: |
|||
|
|||
```Python |
|||
some_variable: PlaneItem | CarItem |
|||
``` |
|||
|
|||
Pero si ponemos eso en la asignación `response_model=PlaneItem | CarItem` obtendríamos un error, porque Python intentaría realizar una **operación inválida** entre `PlaneItem` y `CarItem` en lugar de interpretar eso como anotaciones de tipos. |
|||
Pero si ponemos eso en la asignación `response_model=PlaneItem | CarItem` obtendríamos un error, porque Python intentaría realizar una **operación inválida** entre `PlaneItem` y `CarItem` en lugar de interpretar eso como una anotación de tipos. |
|||
|
|||
## Lista de modelos { #list-of-models } |
|||
|
|||
@ -203,7 +194,6 @@ Para eso, usa el `typing.List` estándar de Python (o simplemente `list` en Pyth |
|||
|
|||
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} |
|||
|
|||
|
|||
## Response con `dict` arbitrario { #response-with-arbitrary-dict } |
|||
|
|||
También puedes declarar un response usando un `dict` arbitrario plano, declarando solo el tipo de las claves y valores, sin usar un modelo Pydantic. |
|||
@ -214,7 +204,6 @@ En este caso, puedes usar `typing.Dict` (o solo `dict` en Python 3.9 y posterior |
|||
|
|||
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} |
|||
|
|||
|
|||
## Recapitulación { #recap } |
|||
|
|||
Usa múltiples modelos Pydantic y hereda libremente para cada caso. |
|||
|
|||
Loading…
Reference in new issue