Actualizar contenido vía AJAX

Introducción

AJAX (Asynchronous JavaScript and XML, JavaScript y XML asíncrono) es una técnica que consiste en realizar una petición al servidor web en paralelo utilizando código JavaScript. Es empleada para actualizar un determinado contenido en una página web sin necesidad de recargar ésta por completo, lo que provee mayor velocidad de transferencia al solicitar únicamente los datos necesarios, mejor apariencia y más comodidad para el usuario.

El cliente (navegador web) realiza una petición en segundo plano a una dirección de URL determinada, utilizando código JavaScript. El servidor recibe la petición y responde con un contenido específico que varía según las necesidades de cada aplicación web; código HTML, XML, JSON, texto plano, entre otros. Una función JavaScript asignada previamente recibe dicho contenido y realiza los cambios necesarios para reflejarlo en la página. El lenguaje utilizado en el servidor es indiferente, como también el método por el cual se ejecuta (CGI, FastCGI, WSGI).

Preparativos

En este artículo se hace uso de, lógicamente, el lenguaje Python y la tecnología CGI, a fin de reflejar un panorama general de la estructura de AJAX y su funcionamiento, para que pueda ser aplicado sin dificultad luego en otros entornos (Django, web.py). Se requieren mínimos conocimentos de JavaScript. El servidor utilizado para ejecutar los scripts CGI a continuación se encuentra en el artículo Programación web vía CGI – Una introducción.

Para demostrar los sencillos pasos de la implementación de AJAX, se utilizará una página de ejemplo que muestra en pantalla el mensaje «Hola mundo». Seguido de éste, un botón que obtiene un nuevo nombre vía AJAX para realizar otro saludo. Por lo tanto, luego de presionar el botón se verá «Hola Recursos Python».

Implementación

Si bien el código Python, HTML y JavaScript pueden estar en un único archivo (véase el apartado «Todo en uno»), en este caso estarán separados para diferenciar claramente el rol de cada uno de estos. El archivo principal será llamado index.py, y se encargará de leer el fichero que contiene código HTML e imprimirlo en pantalla.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Cabecera.
print("Content-Type: text/html; charset=utf-8\n\r")
print("")

with open("index.html") as f:
    print(f.read())

El archivo index.html, en un comienzo, será el siguiente.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
    <title>Ejemplo CGI + AJAX</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
</head>
<body>
    <label id="myLabel">Hola mundo!</label>
</body>
</html>

Con este equipamiento preliminar, al acceder a la dirección http://localhost:8000/index.py veremos lo siguiente.

Vista previa

Para realizar una petición en paralelo, vamos a crear un nuevo archivo llamado ajax.js y colocarlo en una carpeta denominada js, para evitar que el servidor lo interprete como un script CGI.

function asyncChange()
{
    var request;
    
    if (window.XMLHttpRequest) {
        request = new window.XMLHttpRequest();
    } else {
        // Versiones antiguas de Internet Explorer.
        request = new window.ActiveXObject("Microsoft.XMLHTTP");
    }

En esta pequeña porción de código se crea un objeto que representa la petición que se realizará al servidor. El objeto XMLHttpRequest fue diseñado por Microsoft e implementado en la versión 7 de Internet Explorer (disponible vía ActiveX en versiones anteriores). Rápidamente fue adoptado por otros navegadores y estandarizado.

La peitición se inicializa y envía utilizando las funciones open y send del objeto mencionado previamente.

    request.open("GET"          /* Tipo de petición: POST / GET */,
                 "get_name.py"  /* URL a donde se envía la petición */,
                 true           /* Indica si la petición corre en paralelo */
                 );
    request.send();

Por último, se indica una función que es llamada al recibir una respuesta del servidor.

    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            // Actualizar contenido.
            document.getElementById("myLabel").innerHTML = "Hola " + request.responseText + "!";
        }
    }
}

Función completa:

function asyncChange()
{
    var request;
    
    if (window.XMLHttpRequest) {
        request = new window.XMLHttpRequest();
    } else {
        request = new window.ActiveXObject("Microsoft.XMLHTTP");
    }
    
    request.open("GET", "get_name.py", true);
    request.send();
    
    request.onreadystatechange = function()
    {
        if (request.readyState == 4 && request.status == 200)
        {
            document.getElementById("myLabel").innerHTML = "Hola " + request.responseText + "!";
        }
    }
}

A continuación, incluir el archivo en la cabecera del archivo index.html (dentro de las etiquetas <head> y </head>).

<script src="js/ajax.js"></script>

Seguido del elemento myLabel que contiene el mensaje, añadir un botón que llame a la función.

<button onclick="javascript:asyncChange();">Cambiar</button>

Código HTML completo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
    <title>Ejemplo CGI + AJAX</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script src="js/ajax.js"></script>
</head>
<body>
    <label id="myLabel">Hola mundo!</label>
    <button onclick="javascript:asyncChange();">Cambiar</button>
</body>
</html>

Para finalizar, es necesario crear un archivo llamado get_name.py, que retornará un nuevo contenido según lo indicado en la función asyncChange.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

print("Content-Type: text/html")
print("")
print("Recursos Python")

Accedemos nuevamente a http://localhost:8000/index.py.

Vista previa

Y presionamos «Cambiar» para actualizar el contenido vía AJAX.

Vista previa

El mensaje habrá cambiado a «Hola Recursos Python !» (puede utilizarse print("Recursos Python", end="") o bien sys.stdout.write en Python 2.x para evitar el espacio adicional).

A partir de esta introducción al funcionamiento de AJAX en Python, podrán implementarlo para actualizar contenido en sus propias aplicaciones web.

Todo en uno

El siguiente ejemplo incluye el código anterior concentrado en un único script de Python llamado index2.py.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from cgi import FieldStorage

# Cabecera.
print("Content-Type: text/html; charset=utf-8\n\r")
print("")

# Contenido HTML.
if "get_name" in FieldStorage():
    print("Recursos Python")
else:
    print("""
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">
<head>
    <title>Ejemplo CGI + AJAX</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8" />
    <script>
    function asyncChange()
    {
        var request;
        
        if (window.XMLHttpRequest) {
            request = new window.XMLHttpRequest();
        } else {
            request = new window.ActiveXObject("Microsoft.XMLHTTP");
        }
        
        request.open("GET", "index2.py?get_name=1", true);
        request.send();
        
        request.onreadystatechange = function()
        {
            if (request.readyState == 4 && request.status == 200)
            {
                document.getElementById("myLabel").innerHTML = "Hola " + request.responseText + "!";
            }
        }
    }
    </script>
</head>
<body>
    <label id="myLabel">Hola mundo!</label>
    <button onclick="javascript:asyncChange();">Cambiar</button>
</body>
</html>
    """)

Curso online 👨‍💻

¡Ya lanzamos el curso oficial de Recursos Python en Udemy! Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter en 2024.

Consultoría 💡

Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.

3 comentarios.

    • Recursos Python says:

      Hola. Este ejemplo es para CGI, pero se puede adaptar a Flask o a cualquier otro framework. En ese caso pondrías la parte de HTML y JavaScript en los templates, y el resto en las vistas/controladores.

Deja una respuesta