Cómo leer parámetros en un endpoint de Flask

Cómo leer parámetros en un endpoint de Flask
Photo by Artturi Jalli / Unsplash

Cuando construimos una app en Flask, una de las primeras tareas que encontraremos es cómo recuperar los parámetros que vienen como parte de la petición. Específicamente, cuando es una petición de tipo GET, ¿cómo acceder al query string y los valores que vienen dentro?

Petición tipo GET

Empecemos por definir un endpoint en nuestro aplicativo:

@app.route("/mi/ruta", methods=['GET'])
def mi_ruta():
    args = request.args
    param_1 = args.get("param_1")
    param_2 = args.get("param_2")

    print(param_1)
    print(param_2)

    return json.dumps({"mensaje": "Todo bien"})

He definido un endpoint con la ruta /mi/ruta, el cual al momento de ser invocado intenta extraer dos parámetros de la petición, llamados para fines prácticos param_1 y param_2. Lo único que estamos haciendo con ellos de momento es imprimir en consola.

Nuestro endpoint devuelve una respuesta independientemente de si le enviamos o no los parámetros
Puesto que no se le enviaron parámetros a la petición, al intentar imprimir en consola los dos parámetros vemos únicamente "None"

Empecemos por validar que efectivamente los parámetros vengan incluídos en la petición. Para esto hacemos una sencilla validación:

@app.route("/mi/ruta", methods=['GET'])
def mi_ruta():
    args = request.args
    param_1 = args.get("param_1")
    param_2 = args.get("param_2")

    if param_1 is None or param_2 is None:
        return json.dumps({"mensaje": "Faltan los parámetros"})
    else:
        print(param_1)
        print(param_2)
        return json.dumps({"mensaje": "Todo bien"})

Explícitamente estamos asegurándonos que ninguno de los dos parámetros sean omitidos. En caso de faltar cualquiera de los dos, veremos el siguiente mensaje al intentar invocar nuestro endpoint:

No se envió ninguno de los dos parámetros que espera nuestro endpoint
Se envió tanto param_1 y param_2 en la petición

La forma de enviar los parámetros en un endpoint de tipo GET es por supuesto en el querystring. Concatenamos los parámetros como parte de la URL con la que invocamos nuestro endpoint: /mi/ruta?param_1=123&param2_456. Usamos el signo de interrogación (?) para indicar que comenzaremos a listar los parámetros y los separamos con un ampersand (&). Y esto es lo que vemos en consola:

A partir de acá ya podemos utilizar los valores como cualquier otra variable y nuestro aplicativo puede continuar su flujo con los valores que fueron suministrados.

Petición POST

Ahora vamos a cambiar el tipo de petición y ya no recibiremos los parámetros en la URL sino en el cuerpo de la petición. Nuestro endpoint cambia de la siguiente manera:

@app.route("/mi/ruta", methods=['POST'])
def mi_ruta():
    content_type = request.headers.get('Content-Type')
    if content_type == 'application/json':
        try:
            param_1 = request.get_json().get('param_1')
            param_2 = request.get_json().get('param_2')
            if param_1 is None or param_2 is None:
                return json.dumps({"mensaje": "Faltan los parámetros"})
            else:
                print(param_1)
                print(param_2)
                return json.dumps({"mensaje": "Todo bien"})
        except ValueError as error:
            return json.dumps({"mensaje": "Contenido de petición no válido"})
    else:
        return json.dumps({"mensaje": "Contenido de petición no es de tipo JSON"})

En vez de leer el querystring de nuestro endpoint, estamos accediendo al objeto JSON en el cuerpo de la petición. El cuerpo de nuestra petición puede tener distintos tipos, en este caso estamos validando explícitamente si el contenido que estamos recibiendo es de tipo JSON, caso contrario enviamos un mensaje indicando que el tipo de contenido no es el adecuado.

Adicionalmente estamos utilizando un bloque try / except para capturar un sinfín de posibles errores derivados de enviarle un JSON mal formado, un cuerpo vacío o muchas otras posibilidades a nuestro método. Si el contenido viene en un formato correcto, finalmente intentamos extraer param_1 y param_2 del objeto JSON en el cuerpo de nuestra petición. Nuevamente validamos que existan ambos parámetros en la petición y finalmente imprimimos a consola dichos valores y respondemos con un Todo bien.

Mensaje de error cuando no enviamos un contenido a nuestra petición
Mensaje de error cuando enviamos un JSON vacío
Sólo enviamos uno de los dos parámetros que espera nuestro endpoint, mismo mensaje de error
Finalmente enviamos los parámetros requeridos y recibimos la respuesta que esperábamos
Y nuestra consola imprime los valores de ambos parámetros, tal y como se espera

Conclusión

Existen plugins y frameworks que pueden facilitar la validación y adquisición de valores de forma automática de las peticiones que enviamos a un endpoint construido con Flask. Generalmente utilizaremos dichas opciones antes que hacer todo este trabajo manual pero es una buena forma de aprender, o bien cuando no es una opción o estamos en un entorno severamente limitado y no podemos disponer de plugins adicionales, esta es la forma de validar y trabajar manualmente con parámetros en nuestras peticiones.