Cómo personalizar las clases de respuesta en Flask
El ciclo de respuesta comienza cuando regresa la función utilizada por Flask para manejar la solicitud. En las aplicaciones web, las rutas normalmente terminan llamando a la función render_template para representar el archivo de plantilla al que se hace referencia y devolverlo como una cadena:
@app.route('/index')
def index():
# ...
Devuelve render_template('index.html')
Sin embargo, es posible que sepas que la función de ruta de Flask puede opcionalmente devolverá dos valores adicionales, que se establecerán en el código de estado HTTP y los encabezados de respuesta HTTP personalizados:
@app.route( '/data')
def index():
# ...
return render_template('data.json'), 201, {'Content-Type': 'application/json'}
En En el ejemplo anterior, el código de estado se establece en 201, en lugar del 200 predeterminado de Flask, lo que significa que la solicitud se procesó correctamente. Este ejemplo también define un encabezado Content-Type, que indica que la respuesta HTTP contiene datos JSON, ya que Flask lo configurará en HTML de forma predeterminada si no lo configura explícitamente.
El ejemplo anterior describe los tres componentes básicos de una respuesta HTTP, a saber, datos o cuerpo, código de estado y encabezados. El ejemplo de aplicación Flask tiene una función make_response que toma el valor de retorno de la función de enrutamiento (ya sea un valor único o una tupla de 1 a 3 valores) y lo completa en un objeto Response.
Puedes ver todo el proceso a través de una sesión de consola Python. Primero cree un entorno virtual e instale Flask, luego abra una sesión de Python e ingrese el siguiente código:
>>> from flask import Flask
>> app = Flask(name__)< / p>
>.make_response(('Hello, World', 201))
Aquí, creé la aplicación Flask Una instancia simple del programa y luego llama al método make_response() para crear un objeto de clase de respuesta. En la primera llamada, pasé una cadena como parámetro, por lo que el código de estado y los encabezados predeterminados se usaron en el objeto de respuesta. En la segunda llamada, paso una tupla de dos valores, forzando así la devolución de un código de estado no predeterminado. Tenga en cuenta que la segunda llamada utiliza dos paréntesis, el paréntesis interior encierra la cadena y el código de estado en una tupla. Esto es necesario porque la función make_response() solo acepta un argumento.
Después de que Flask crea el objeto de respuesta (que representa el valor de retorno de la función de enrutamiento), también realizará algún procesamiento. Esto incluye pasar el objeto de respuesta a un controlador after_request personalizado, donde la aplicación también puede insertar o modificar encabezados, cambiar el cuerpo o el código de estado, o incluso habilitar un objeto de respuesta completamente nuevo si lo desea. Finalmente, Flask obtendrá el objeto de respuesta final, lo convertirá en una respuesta HTTP y lo enviará al cliente.
Clases reactivas en Flask
Echemos un vistazo a las características más interesantes de las clases receptivas.
La siguiente definición de clase demuestra lo que creo que son las propiedades y métodos flexibles que tiene esta clase:
Respuesta de clase:
charset = 'utf-8'
default_status = 200
default_mimetype = 'text/html'
def __init__(self, respuesta=Ninguno, estado=Ninguno, encabezados=Ninguno,
mimetype= Ninguno, content_type=Ninguno, direct_passthrough=False):
pass
@classmethod
def force_type(cls, respuesta, entorno=Ninguno):
pasar
Tenga en cuenta que si verifica el código fuente de Flask, no encontrará la definición de clase anterior. La clase Response en Flask en realidad se deriva de una clase del mismo nombre en la biblioteca Werzeug. La clase Response en Werzeug hereda de la clase BaseResponse que contiene la definición anterior.
Los atributos de clase charset, default_status y default_mimetype definen valores predeterminados. Si alguno de los valores predeterminados no se aplica a su aplicación, puede subclasificar la clase Respuesta para definir sus propios valores predeterminados sin establecer valores personalizados en cada objeto de respuesta. Por ejemplo, si su aplicación es una interfaz API y todas las rutas devuelven datos en formato XML, puede cambiar default_mimetype en su clase personalizada a application/xml para que Flask devuelva respuestas XML de forma predeterminada. Verás cómo lograr esto más adelante.
No entraré en detalles sobre el constructor __init__ aquí (puede leer la documentación de Werkzeug), pero tenga en cuenta que hay tres elementos importantes en el objeto de respuesta de Flask, a saber, el cuerpo de la respuesta, el estado, el código y los encabezados se pasarán como parámetros. En las subclases, los constructores pueden cambiar las reglas correspondientes para crear respuestas.
El método de clase force_type() en la clase de respuesta es el único elemento más complejo pero importante. A veces, Werkzeug o Flask necesitan crear su propio objeto de respuesta, como cuando ocurre un error en la aplicación y debe devolverse al cliente. En este caso, el objeto de respuesta no lo proporciona la aplicación sino que lo crea el marco. En aplicaciones que usan clases de respuesta personalizadas, Flask y Werkzeug no conocen los detalles de la clase personalizada, por lo que usan la clase de respuesta estándar para crear la respuesta. El método force_type() en las clases de respuesta está diseñado para aceptar instancias de diferentes clases de respuesta y convertirlas a su propio formato.
Creo que debes estar confundido por la descripción del método force_type(). Claramente, lo que significa es que si Flask encuentra un objeto de respuesta diferente al que espera, utilizará este método para convertirlo. El tercer escenario de uso que analizaré a continuación aprovecha esto y permite que la función de enrutamiento de Flask devuelva algo como un diccionario, una lista o cualquier otro objeto personalizado como objeto de respuesta a la solicitud.
Bien, eso es todo por la teoría. A continuación, déjame mostrarte cómo aplicar los consejos anteriores sobre las clases de respuesta. ¿Estás listo?
Uso de clases de respuesta personalizadas
En este punto, creo que estará de acuerdo: en algunos escenarios de aplicaciones interesantes, el uso de clases de respuesta personalizadas será de gran beneficio. Antes de darles un ejemplo práctico, quiero mostrarles lo fácil que es configurar y usar una clase de respuesta personalizada en Flask.
Consulte el siguiente ejemplo:
from flask import Flask, Response
class MyResponse(Response):
pass
app = Flask (__name__)
app.response_class = MyResponse
# ...
En el código anterior, definí una respuesta personalizada denominada tipo MyResponse. Normalmente, una clase de respuesta personalizada agrega o modifica el comportamiento de la clase predeterminada, por lo que esto generalmente se logra subclasificando la clase de respuesta en Flask. Para que Flask use una clase personalizada, simplemente configuro app.response_class.
Response_class en la clase Flask es un atributo de clase, por lo que podemos modificar ligeramente el ejemplo anterior y crear una subclase Flask con una configuración de clase Response personalizada:
from flask import Flask, Response
clase MiRespuesta(Respuesta):
pasar
clase MiFlask(Flask)
response_class = MiRespuesta
aplicación = MiFlask(__nombre__)
# ...