Saltar a contenido

Parámetros de ruta#

iThome Ironman 2024

Este es el décimo artículo de la serie tutorial de Django Ninja.

En el artículo anterior, presentamos cómo maneja Django Ninja las solicitudes HTTP y destacamos su estrecha integración con los type hints de Python.

Este artículo explorará la aplicación y los detalles de los parámetros de ruta (path parameters) en Django Ninja, algo sumamente común al procesar solicitudes HTTP, especialmente en API RESTful.

Los cambios de código en el proyecto de ejemplo para este artículo se concentran en este PR.

Proyecto de ejemplo en GitHub#

👉 Django-Ninja-Tutorial


1. ¿Qué son los Path Parameters?#

Los path parameters son una parte constitutiva de la URL. Se ubican en posiciones específicas dentro de la ruta (path) de la dirección web y determinan el contenido transmitido según diferentes valores (parámetros), utilizándose para especificar recursos dinámicamente.

Conviene primero comprender la posición del path dentro de toda la URL: (Imagen tomada de Wikipedia)

Haz clic en la imagen para ampliar

Como se puede apreciar en la imagen, la ruta (path) forma parte de la URL y, de hecho, es una parte requerida.

Sin embargo, ten en cuenta que los path parameters son solo una «funcionalidad» que ofrecen marcos de trabajo como Django y Django Ninja. Para la URL en sí, el path es solo el path: una simple cadena de texto.

Ejemplo de parámetros de ruta#

Veamos un ejemplo sencillo para comprender mejor el concepto de path parameters.

@router.get(path='/posts/{post_id}/')  # {post_id} es el parámetro de ruta

Al hacer la solicitud real, 123 representa el id de una publicación específica a través del parámetro de ruta:

GET /posts/123

Como es de esperar, si fuera 456 o 789, obtendrías resultados diferentes.

Esto le otorga flexibilidad a la API, permitiendo operar sobre diferentes recursos sin tener que crear una ruta diferente para cada recurso: sus endpoints y rutas son idénticos, cambiando únicamente los «parámetros».


2. Cambios en el proyecto de ejemplo#

A continuación, utilicemos el código del proyecto de ejemplo para ir explicando y demostrando el contenido de este artículo.

Pero primero debemos realizar dos modificaciones.

Modificación 1: eliminar el prefijo de ruta de primer nivel#

Eliminar los prefijos de ruta de primer nivel /posts/ y /user/, para que la ruta en el decorador router de la función view sea más completa y fácil de leer.

Originalmente era así:

@router.get(path='/{post_id}/')  # El prefijo de ruta se definió en la ruta de primer nivel del proyecto

Ahora es así:

@router.get(path='/posts/{post_id}/')  # Todo pasa a definirse en la ruta de segundo nivel de la app

Ten en cuenta que esto se hace para mejorar la experiencia de aprendizaje; en el trabajo práctico normalmente no haríamos esto, pues se perdería la ventaja de las rutas modulares.

Modificación 2: añadir una API nueva#

Para demostrar los path parameters, debemos contar con una API que ponga en práctica esta funcionalidad.

Añadimos una API para «obtener la información de una sola publicación».


Bien, habiendo aclarado esto, podemos comenzar a comprender los path parameters.

Todo el código siguiente está tomado del proyecto de ejemplo.

3. Uso de Path Parameters en Django Ninja#

En Django Ninja, definir parámetros de ruta es sumamente sencillo. A través del decorador router y los type hints, podemos manejar estos parámetros fácilmente y realizar la conversión automática de tipos.

Definir una API «con parámetros de ruta»#

Veamos cómo definir una API con parámetros de ruta en Django Ninja:

@router.get(path='/posts/{post_id}/')
def get_post(request: HttpRequest, post_id: int) -> Post:
    post = Post.objects.get(id=post_id)
    return post

En el ejemplo, {post_id} es un parámetro de ruta; la cadena de texto completa del path será analizada (parsing) y pasada al parámetro post_id dentro de la función get_post.

Django Ninja realizará automáticamente la conversión de tipos según el tipo definido en la firma de la función.

Por ejemplo, si en la función view marcamos post_id: int, Django Ninja convertirá automáticamente el parámetro en cadena proveniente de la URL a un int.

En otras palabras, el flujo de procesamiento de path parameters ofrece simultáneamente dos efectos:

  1. Validación de tipos de parámetros: Evita que el frontend envíe un post_id con un tipo incorrecto y que la función view siga intentando procesar ese valor internamente hasta que ocurra un error.
  2. Conversión automática de tipos dentro de la función view: Te ahorra el trabajo de hacer la conversión manual dentro de la función.

4. Compatibilidad con los Path Converters nativos de Django#

Al procesar URL, Django ofrece originalmente los «path converters» para permitirte hacer una «coincidencia estricta» sobre las rutas de solicitud.

Solo si la coincidencia es exitosa, se «reenviará» la solicitud HTTP a la función view específica.

Lo «estricto» aquí significa que el tipo debe coincidir con lo definido por el path converter para que la coincidencia sea exitosa.

Los tipos comunes de converters incluyen str, int y slug, los cuales pueden limitar el formato de los parámetros en la URL:

path('posts/<int:post_id>/', views.get_post),

<int:post_id> es un path converter que requiere que post_id sea un número entero.

Vale la pena destacar que el objetivo principal de los path converters no es la conversión de tipos (eso es solo secundario), sino el «patrón de coincidencia» (pattern matching) de la ruta del endpoint.

Cuando el patrón no coincide, simplemente no habrá coincidencia, y por supuesto no se realizará ninguna conversión de tipo.

Path Converters en Django Ninja#

En Django Ninja, estos path converters nativos se pueden seguir utilizando y se han simplificado aún más.

Simplemente escríbelos directamente dentro de la cadena de ruta del decorador router:

@router.get(path='/posts/{int:post_id}/')

Como se mencionó antes, con el path converter, si post_id no es un int válido, la coincidencia del patrón URL fallará directamente: la solicitud no llegará a la función view y no habrá ninguna conversión de tipo.

Si no hay otra ruta que coincida con éxito, Django devolverá directamente «404 Not Found».

Personalmente opino que en Django Ninja la función de los path converters ha sido reemplazada parcialmente por los type hints. Si se desean utilizar path converters al mismo tiempo, hay que prestar atención al orden de evaluación (los path converters evalúan primero) y asegurar que los tipos configurados en ambos sean idénticos.


5. Manejo básico de errores en solicitudes#

Cuando los parámetros de ruta en una solicitud no coinciden con el tipo definido por los type hints, Django Ninja devolverá automáticamente una respuesta HTTP con un mensaje de error y contenido descriptivo, con el código de estado 422.

Por ejemplo, si el usuario solicita la ruta /posts/abc/ (el parámetro post_id no es un número), obtendrá la siguiente respuesta:

// http://127.0.0.1:8000/posts/abc/
{
    "detail": [
        {
            "type": "int_parsing",
            "loc": [
                "path",
                "post_id"
            ],
            "msg": "Input should be a valid integer, unable to parse string as an integer"
        }
    ]
}

Este mecanismo de manejo automático de errores no solo mejora la estabilidad de la API, sino que también simplifica la lógica de manejo de errores del desarrollador.

La respuesta 422 integrada es sumamente común en Django Ninja y nos ahorra bastante tiempo.


Resumen y siguientes pasos#

Los parámetros de ruta son un componente fundamental en las API RESTful. A través de type hints y el manejo automatizado de errores, Django Ninja nos permite procesar parámetros dinámicos en las rutas con facilidad.

Además, mantiene una excelente compatibilidad con los path converters nativos de Django, ofreciendo una experiencia de desarrollo eficiente y limpia.

En el próximo artículo, profundizaremos en los parámetros de consulta (query parameters), explicando cómo manejar estos parámetros en Django Ninja para mejorar aún más la flexibilidad y funcionalidad de la API.