Tutorial

Cómo procesar los datos de solicitud entrantes en Flask

Published on March 19, 2021
author

Anthony Herbert

Español
Cómo procesar los datos de solicitud entrantes en Flask

Introducción

Las aplicaciones web requieren con frecuencia el procesamiento de los datos de las solicitudes entrantes de los usuarios. Esta carga útil puede tener la forma de cadenas de consulta, datos de formulario y objetos JSON. Flask, como cualquier otro marco web, le permite acceder a los datos de la solicitud.

En este tutorial, se creará una aplicación Flask con tres rutas que aceptan cadenas de consulta, datos de formulario u objetos JSON.

Requisitos previos

Para completar este tutorial, necesitará lo siguiente:

  • Este proyecto requerirá que Python se instale en un entorno local.
  • Este proyecto usará Pipenv, una herramienta preparada para la producción que pretende traer lo mejor de todos los mundos de empaquetado al mundo de Python. Aprovecha Pipfile, pip, y virtualenv en un solo comando.
  • Se requerirá descargar e instalar una herramienta como Postman para probar los puntos finales de API.

Este tutorial se verificó con Pipenv v2020.11.15, Python v3.9.0 y Flask v1.1.2.

Configuración del proyecto

Para demostrar las diferentes formas de usar solicitudes, deberá crear una aplicación Flask. Aunque la aplicación de ejemplo utiliza una estructura simplificada para las funciones y las rutas de vista, lo que se aprende en este tutorial puede aplicarse a cualquier método de organización de las vistas, como las vistas basadas en clases, los planos o una extensión como Flask-Via.

Primero, deberá crear un directorio de proyecto. Abra su terminal y ejecute el siguiente comando:

  1. mkdir flask_request_example

Luego, diríjase al nuevo directorio:

  1. cd flask_request_example

Luego, instale Flask. Abra su terminal y ejecute el siguiente comando:

  1. pipenv install Flask

El comando pipenv creará un virtualenv para este proyecto, un Pipfile, para instalar flask y un Pipfile.lock.

Para activar el virtualenv del proyecto, ejecute el siguiente comando:

  1. pipenv shell

Para acceder a los datos entrantes en Flask, tiene que usar el objeto request. El objeto request contiene todos los datos entrantes de la solicitud, que incluye el mimetype, recomendante, dirección IP, datos sin procesar, HTTP y encabezados, entre otras cosas.

Aunque toda la información que contiene el objeto de solicitud puede ser útil, para los propósitos de este artículo, se centrará en los datos que normalmente son suministrados directamente por la persona que llama al punto final.

Para obtener acceso al objeto de solicitud en Flask, deberá importarlo desde la biblioteca Flask:

from flask import request

Luego, podrá usarlo en cualquiera de sus funciones de vista.

Utilice su editor de código para crear un archivo app.py. Importe Flask y el objeto request. Y también establezca rutas para query-example, form-example, y json-example:

app.py
# import main Flask class and request object
from flask import Flask, request

# create the Flask app
app = Flask(__name__)

@app.route('/query-example')
def query_example():
    return 'Query String Example'

@app.route('/form-example')
def form_example():
    return 'Form Data Example'

@app.route('/json-example')
def json_example():
    return 'JSON Object Example'

if __name__ == '__main__':
    # run app in debug mode on port 5000
    app.run(debug=True, port=5000)

Luego, abra su terminal e inicie la aplicación con el siguiente comando:

  1. python app.py

La aplicación se iniciará en el puerto 5000, por lo que puede ver cada ruta en su navegador con los siguientes enlaces:

http://127.0.0.1:5000/query-example (or localhost:5000/query-example)
http://127.0.0.1:5000/form-example (or localhost:5000/form-example)
http://127.0.0.1:5000/json-example (or localhost:5000/json-example)

El código establece tres rutas y visitar cada una de ellas mostrará los mensajes de "Query String Example", "Form Data Example" y "JSON Object Example", respectivamente.

Uso de argumentos Query

Los argumentos de URL que se añaden a una cadena de consulta son una forma común de pasar los datos a una aplicación web. Al navegar por la web, es probable que haya encontrado alguna vez una cadena de consulta.

Una cadena de consulta se parece a lo siguiente:

example.com?arg1=value1&arg2=value2

La cadena de consulta comienza después del carácter de signo de interrogación (?) :

example.com?arg1=value1&arg2=value2

Y tiene pares clave-valor separados por un carácter de “y” comercial (&):

example.com?arg1=value1&arg2=value2

Para cada par, la clave va seguida por un signo de igualdad (=) y, a continuación, el valor.

arg1 : value1
arg2 : value2

Las cadenas de consulta son útiles para pasar datos que no requieren que el usuario realice ninguna acción. Puede generar una cadena de consulta en algún lugar de su aplicación y añadirla a una URL para que cuando un usuario realice una solicitud, los datos se pasen automáticamente para ellos. Una cadena de consulta también puede generarse a través de formularios que tienen GET como método.

Vamos a añadir una cadena de consulta a la ruta query-example. En este ejemplo hipotético, se proporcionará el nombre de un lenguaje de programación que se mostrará en la pantalla. Cree una clave de "language" y un valor de "Python":

http://127.0.0.1:5000/query-example?language=Python

Si ejecuta la aplicación y navega a esa URL, verá que sigue mostrando un mensaje de "Query String Example".

Tendrá que programar la parte que maneja los argumentos de la consulta. Este código leerá la clave de language usando request.args.get('language') o request.args['language'].

Al invocar request.args.get('language'), la aplicación continuará ejecutándose si la clave de language no existe en la URL. En ese caso, el resultado del método será None.

Al invocar request.args['language'], la aplicación mostrará un error 400 si la clave de language no existe en la URL.

Cuando se trata de cadenas de consulta, se recomienda usar request.args.get() para evitar que la aplicación falle.

Vamos a leer la clave language y mostrarla como resultado.

Modifique la ruta query-example en app.py con el siguiente código:

app.py
@app.route('/query-example')
def query_example():
    # if key doesn't exist, returns None
    language = request.args.get('language')

    return '''<h1>The language value is: {}</h1>'''.format(language)

Luego, ejecute la aplicación y diríjase a la URL:

http://127.0.0.1:5000/query-example?language=Python

El navegador debe mostrar el siguiente mensaje:

Output
The language value is: Python

El argumento de la URL se asigna a la variable language y luego se devuelve al navegador.

Para añadir más parámetros de cadena de consulta, puede añadir ampersands y los nuevos pares clave-valor al final de la URL. Cree una clave de "framework" y un valor de "Flask":

http://127.0.0.1:5000/query-example?language=Python&framework=Flask

Y si desea más, continúe añadiendo ampersands y pares clave-valor. Cree una clave de "website" y un valor de "DigitalOcean":

http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean

Para obtener acceso a esos valores, seguirá usando request.args.get() o request.args[]. Vamos a usar ambos para demostrar lo que sucede cuando falta una clave. Modifique la ruta query_example para asignar el valor de los resultados a variables y luego mostrarlos:

@app.route('/query-example')
def query_example():
    # if key doesn't exist, returns None
    language = request.args.get('language')

    # if key doesn't exist, returns a 400, bad request error
    framework = request.args['framework']

    # if key doesn't exist, returns None
    website = request.args.get('website')

    return '''
              <h1>The language value is: {}</h1>
              <h1>The framework value is: {}</h1>
              <h1>The website value is: {}'''.format(language, framework, website)

Luego, ejecute la aplicación y diríjase a la URL:

http://127.0.0.1:5000/query-example?language=Python&framework=Flask&website=DigitalOcean

El navegador debe mostrar el siguiente mensaje:

Output
The language value is: Python The framework value is: Flask The website value is: DigitalOcean

Elimine la clave de language de la URL:

http://127.0.0.1:5000/query-example?framework=Flask&website=DigitalOcean

El navegador debe mostrar el siguiente mensaje con None cuando no se proporciona un valor para language:

Output
The language value is: None The framework value is: Flask The website value is: DigitalOcean

Elimine la clave de framework de la URL:

http://127.0.0.1:5000/query-example?language=Python&website=DigitalOcean

El navegador debería encontrar un error porque está esperando un valor para framework:

Output
werkzeug.exceptions.BadRequestKeyError werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. KeyError: 'framework'

Ahora, ya comprende cómo se manejan las cadenas de consulta. Continuemos con el siguiente tipo de datos entrantes.

Uso de datos de formulario

Los datos de formulario provienen de un formulario que ha sido enviado como solicitud POST a una ruta. Por lo tanto, en lugar de ver los datos en la URL (excepto en los casos en que el formulario se envía con una solicitud GET), los datos del formulario pasarán a la aplicación entre bastidores. Aunque no se pueden ver fácilmente los datos del formulario que se pasan, su aplicación puede leerlos.

Para demostrarlo, modifique la ruta de form-example en app.py para aceptar las solicitudes GET y POST, y devolver un formulario:

app.py
# allow both GET and POST requests
@app.route('/form-example', methods=['GET', 'POST'])
def form_example():
    return '''
              <form method="POST">
                  <div><label>Language: <input type="text" name="language"></label></div>
                  <div><label>Framework: <input type="text" name="framework"></label></div>
                  <input type="submit" value="Submit">
              </form>'''

Luego, ejecute la aplicación y diríjase a la URL:

http://127.0.0.1:5000/form-example

El navegador debe mostrar un formulario con dos campos de entrada, uno para language y otro para framework, así como para un botón de envío.

Lo más importante que hay que saber sobre este formulario es que realiza una solicitud POST a la misma ruta que generó el formulario. Las claves que se leerán en la aplicación provienen de los atributos de nombre de las entradas de nuestro formulario. En este caso, language y framework son los nombres de las entradas, por lo que tendrá acceso a ellos en la aplicación.

Dentro de la función de vista, deberá verificar si el método de solicitud es GET o POST. Si es una solicitud GET, puede mostrar el formulario. De lo contrario, si se trata de una solicitud POST, entonces querrá procesar los datos entrantes.

Modifique la ruta de form-example en app.py con el siguiente código:

app.py
# allow both GET and POST requests
@app.route('/form-example', methods=['GET', 'POST'])
def form_example():
    # handle the POST request
    if request.method == 'POST':
        language = request.form.get('language')
        framework = request.form.get('framework')
        return '''
                  <h1>The language value is: {}</h1>
                  <h1>The framework value is: {}</h1>'''.format(language, framework)

    # otherwise handle the GET request
    return '''
           <form method="POST">
               <div><label>Language: <input type="text" name="language"></label></div>
               <div><label>Framework: <input type="text" name="framework"></label></div>
               <input type="submit" value="Submit">
           </form>'''

Luego, ejecute la aplicación y diríjase a la URL:

http://127.0.0.1:5000/form-example

Complete el campo de language con el valor de Python y el campo de framework con el valor de Flask. Luego, presione Submit (Enviar).

El navegador debe mostrar el siguiente mensaje:

Output
The language value is: Python The framework value is: Flask

Ahora, entiende cómo manejar los datos del formulario. Continuaremos con el siguiente tipo de datos entrantes.

Uso de datos JSON

Los datos JSON generalmente se construye a través de un proceso que invoca la ruta.

Un ejemplo de objeto JSON tiene el siguiente aspecto:

{
  "language": "Python",
  "framework": "Flask",
  "website": "Scotch",
  "version_info": {
    "python": "3.9.0",
    "flask": "1.1.2"
  },
  "examples": ["query", "form", "json"],
  "boolean_test": true
}

Esta estructura puede permitir que se pasen datos mucho más complicados en lugar de las cadenas de consulta y los datos del formulario. En el ejemplo, se ve los objetos JSON anidados y una matriz de elementos. Flask puede gestionar este formato de datos.

Modifique la ruta de form-example en app.py para aceptar las solicitudes POST e ignore otras solicitudes como GET:

app.py
@app.route('/json-example', methods=['POST'])
def json_example():
    return 'JSON Object Example'

A diferencia del navegador web que se utiliza para las cadenas de consulta y los datos de formulario, para los fines de este artículo, para enviar un objeto JSON, se utilizará Postman para enviar solicitudes personalizadas a las URL.

Nota: Si necesita ayuda para navegar por la interfaz de Postman para las solicitudes, consulte la documentación oficial.

En Postman, añada la URL y cambie el tipo a POST. En la pestaña de cuerpo, cambie a raw y seleccione JSON en el menú desplegable.

Estos ajustes son necesarios para que Postman pueda enviar datos JSON correctamente, y para que su aplicación Flask comprenda que está recibiendo JSON:

POST http://127.0.0.1:5000/json-example
Body
raw JSON

Luego, copie el ejemplo JSON anterior en la entrada de texto.

Envíe la solicitud y debería obtener "JSON Object Example" como respuesta. Eso es bastante decepcionante, pero es de esperar porque el código para gestionar la respuesta de los datos JSON aún no se ha escrito.

Para leer los datos, debe entender cómo Flask traduce los datos JSON en las estructuras de datos de Python:

  • Cualquier cosa que sea un objeto se convierte en una dictadura de Python. {"key" : "value"} en JSON corresponde a somedict['key'], que devuelve un valor en Python.
  • Una matriz en JSON se convierte en una lista en Python. Dado que la sintaxis es la misma, aquí hay un ejemplo de una lista: [1,2,3,4,5].
  • Los valores dentro de las comillas en el objeto JSON se convierten en cadenas en Python.
  • Los booleanos true y false se convierten en True y False en Python.
  • Por último, los números sin comillas se convierten en números en Python.

Ahora vamos a trabajar en el código para leer los datos JSON entrantes.

Primero, vamos a asignar todo desde el objeto JSON a una variable usando request.get_json().

request.get_json() convierte el objeto JSON en datos de Python. Asignemos los datos de la solicitud entrante a las variables y devolvámoslos haciendo los siguientes cambios en la ruta json-example:

app.py
# GET requests will be blocked
@app.route('/json-example', methods=['POST'])
def json_example():
    request_data = request.get_json()

    language = request_data['language']
    framework = request_data['framework']

    # two keys are needed because of the nested object
    python_version = request_data['version_info']['python']

    # an index is needed because of the array
    example = request_data['examples'][0]

    boolean_test = request_data['boolean_test']

    return '''
           The language value is: {}
           The framework value is: {}
           The Python version is: {}
           The item at index 0 in the example list is: {}
           The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)

Tenga en cuenta cómo se accede a los elementos que no están en el nivel superior. Se utiliza ['version']['python'] porque se está entrando en un objeto anidado. Y ['examples'][0] se utiliza para acceder al índice 0 en la matriz de ejemplos.

Si el objeto JSON enviado con la solicitud no tiene una clave a la que se accede en su función de vista, entonces la solicitud fallará. Si no quiere que la solicitud falle cuando no existe una clave, tendrá que verificar si la clave existe antes de intentar ingresarla.

app.py
# GET requests will be blocked
@app.route('/json-example', methods=['POST'])
def json_example():
    request_data = request.get_json()

    language = None
    framework = None
    python_version = None
    example = None
    boolean_test = None

    if request_data:
        if 'language' in request_data:
            language = request_data['language']

        if 'framework' in request_data:
            framework = request_data['framework']

        if 'version_info' in request_data:
            if 'python' in request_data['version_info']:
                python_version = request_data['version_info']['python']

        if 'examples' in request_data:
            if (type(request_data['examples']) == list) and (len(request_data['examples']) > 0):
                example = request_data['examples'][0]

        if 'boolean_test' in request_data:
            boolean_test = request_data['boolean_test']

    return '''
           The language value is: {}
           The framework value is: {}
           The Python version is: {}
           The item at index 0 in the example list is: {}
           The boolean value is: {}'''.format(language, framework, python_version, example, boolean_test)

Ejecute la aplicación y envíe la solicitud JSON de ejemplo usando Postman. En la respuesta, obtendrá el siguiente resultado:

Output
The language value is: Python The framework value is: Flask The Python version is: 3.9 The item at index 0 in the example list is: query The boolean value is: false

Ahora comprende cómo se manejan los objetos JSON.

Conclusión

En este artículo, se creó una aplicación Flask con tres rutas que aceptan cadenas de consulta, datos de formulario u objetos JSON.

Además, recuerde que todos los enfoques tuvieron que abordar la consideración recurrente de fallar con gracia cuando falta una clave.

Advertencia: Un tema que no se cubrió en este artículo fue cómo desinfectar la entrada de los usuarios. La sanitización de la entrada de lo usuario garantizaría que los datos leídos por la aplicación no causen un fallo inesperado o que se salten las medidas de seguridad.

Si desea obtener más información sobre Flask, consulte nuestra página del tema Flask para consultar ejercicios y proyectos de programación.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Anthony Herbert

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.