# Parámetros de Path { #path-parameters }
Puedes declarar "parámetros" o "variables" de path con la misma sintaxis que se usa en los format strings de Python:
{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *}
El valor del parámetro de path `item_id` se pasará a tu función como el argumento `item_id`.
Así que, si ejecutas este ejemplo y vas a http://127.0.0.1:8000/items/foo, verás un response de:
```JSON
{"item_id":"foo"}
```
## Parámetros de path con tipos { #path-parameters-with-types }
Puedes declarar el tipo de un parámetro de path en la función, usando anotaciones de tipos estándar de Python:
{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *}
En este caso, `item_id` se declara como un `int`.
/// check | Revisa
Esto te dará soporte del editor dentro de tu función, con chequeo de errores, autocompletado, etc.
///
## Conversión de datos { #data-conversion }
Si ejecutas este ejemplo y abres tu navegador en http://127.0.0.1:8000/items/3, verás un response de:
```JSON
{"item_id":3}
```
/// check | Revisa
Nota que el valor que tu función recibió (y devolvió) es `3`, como un `int` de Python, no un string `"3"`.
Entonces, con esa declaración de tipo, **FastAPI** te ofrece "parsing" automático de request.
///
## Validación de datos { #data-validation }
Pero si vas al navegador en http://127.0.0.1:8000/items/foo, verás un bonito error HTTP de:
```JSON
{
"detail": [
{
"type": "int_parsing",
"loc": [
"path",
"item_id"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "foo"
}
]
}
```
porque el parámetro de path `item_id` tenía un valor de `"foo"`, que no es un `int`.
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
/// check | Revisa
Entonces, con la misma declaración de tipo de Python, **FastAPI** te ofrece validación de datos.
Nota que el error también indica claramente el punto exacto donde la validación falló.
Esto es increíblemente útil mientras desarrollas y depuras código que interactúa con tu API.
///
## Documentación { #documentation }
Y cuando abras tu navegador en http://127.0.0.1:8000/docs, verás una documentación de API automática e interactiva como:
/// check | Revisa
Nuevamente, solo con esa misma declaración de tipo de Python, **FastAPI** te ofrece documentación automática e interactiva (integrando Swagger UI).
Nota que el parámetro de path está declarado como un entero.
///
## Beneficios basados en estándares, documentación alternativa { #standards-based-benefits-alternative-documentation }
Y porque el esquema generado es del estándar OpenAPI, hay muchas herramientas compatibles.
Debido a esto, el propio **FastAPI** proporciona una documentación de API alternativa (usando ReDoc), a la cual puedes acceder en http://127.0.0.1:8000/redoc:
De la misma manera, hay muchas herramientas compatibles. Incluyendo herramientas de generación de código para muchos lenguajes.
## Pydantic { #pydantic }
Toda la validación de datos se realiza internamente con Pydantic, así que obtienes todos los beneficios de esta. Y sabes que estás en buenas manos.
Puedes usar las mismas declaraciones de tipo con `str`, `float`, `bool` y muchos otros tipos de datos complejos.
Varios de estos se exploran en los siguientes capítulos del tutorial.
## El orden importa { #order-matters }
Al crear *path operations*, puedes encontrarte en situaciones donde tienes un path fijo.
Como `/users/me`, imaginemos que es para obtener datos sobre el usuario actual.
Y luego también puedes tener un path `/users/{user_id}` para obtener datos sobre un usuario específico por algún ID de usuario.
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}`:
{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *}
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:
{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *}
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 `Enum` estándar de Python.
### Crear una clase `Enum` { #create-an-enum-class }
Importa `Enum` y crea una subclase que herede de `str` y de `Enum`.
Al heredar de `str`, la documentación de la API podrá saber que los valores deben ser de tipo `string` y podrá representarlos correctamente.
Luego crea atributos de clase con valores fijos, que serán los valores válidos disponibles:
{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *}
/// tip | Consejo
Si te estás preguntando, "AlexNet", "ResNet" y "LeNet" son solo nombres de modelos de Machine Learning.
///
### Declarar un *path parameter* { #declare-a-path-parameter }
Luego crea un *path parameter* con una anotación de tipo usando la clase enum que creaste (`ModelName`):
{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
### Revisa la documentación { #check-the-docs }
Como los valores disponibles para el *path parameter* están predefinidos, la documentación interactiva puede mostrarlos de manera ordenada:
### Trabajando con *enumeraciones* de Python { #working-with-python-enumerations }
El valor del *path parameter* será un *miembro* de enumeración.
#### Comparar *miembros* de enumeraciones { #compare-enumeration-members }
Puedes compararlo con el *miembro* de enumeración en tu enum creada `ModelName`:
{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *}
#### Obtener el valor de *enumeración* { #get-the-enumeration-value }
Puedes obtener el valor actual (un `str` en este caso) usando `model_name.value`, o en general, `your_enum_member.value`:
{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *}
/// tip | Consejo
También podrías acceder al valor `"lenet"` con `ModelName.lenet.value`.
///
#### Devolver *miembros* de enumeración { #return-enumeration-members }
Puedes devolver *miembros de enum* desde tu *path operation*, incluso anidados en un cuerpo JSON (por ejemplo, un `dict`).
Serán convertidos a sus valores correspondientes (cadenas en este caso) antes de devolverlos al cliente:
{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *}
En tu cliente recibirás un response JSON como:
```JSON
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
```
## Parámetros de path conteniendo paths { #path-parameters-containing-paths }
Imaginemos que tienes una *path operation* con un path `/files/{file_path}`.
Pero necesitas que `file_path` en sí mismo contenga un *path*, como `home/johndoe/myfile.txt`.
Entonces, la URL para ese archivo sería algo como: `/files/home/johndoe/myfile.txt`.
### Soporte de OpenAPI { #openapi-support }
OpenAPI no soporta una manera de declarar un *path parameter* para que contenga un *path* dentro, ya que eso podría llevar a escenarios que son difíciles de probar y definir.
Sin embargo, todavía puedes hacerlo en **FastAPI**, usando una de las herramientas internas de Starlette.
Y la documentación seguiría funcionando, aunque no agregue ninguna documentación indicando que el parámetro debe contener un path.
### Convertidor de Path { #path-convertor }
Usando una opción directamente de Starlette puedes declarar un *path parameter* conteniendo un *path* usando una URL como:
```
/files/{file_path:path}
```
En este caso, el nombre del parámetro es `file_path`, y la última parte, `:path`, indica que el parámetro debería coincidir con cualquier *path*.
Así que, puedes usarlo con:
{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *}
/// tip | Consejo
Podrías necesitar que el parámetro contenga `/home/johndoe/myfile.txt`, con una barra inclinada (`/`) inicial.
En ese caso, la URL sería: `/files//home/johndoe/myfile.txt`, con una doble barra inclinada (`//`) entre `files` y `home`.
///
## Resumen { #recap }
Con **FastAPI**, al usar declaraciones de tipo estándar de Python, cortas e intuitivas, obtienes:
* Soporte del editor: chequeo de errores, autocompletado, etc.
* " parsing " de datos
* Validación de datos
* Anotación de API y documentación automática
Y solo tienes que declararlos una vez.
Probablemente esa sea la principal ventaja visible de **FastAPI** en comparación con otros frameworks alternativos (aparte del rendimiento bruto).