Qué es REST

Qué es REST
Photo by Ferenc Almasi / Unsplash

Recientemente inicié un proyecto para generar un control de planos cartográficos, que permitirá administrar las actualizaciones cartográficas, buscar un plano específico por diferentes criterios y entregar planos agrupados por entidad, municipio y localidad, entre otros.

Ahora, he dividido el proyecto en FrontEnd y BackEnd, este último lo estoy haciendo en Django y tendrá dos interfaces de usuario, como demostración, en ReactJS y en Flutter, con el que se podrán generar aplicaciones Web, para escritorio y para Android.

Debido a este esquema, la aplicación en Django, de la que nos ocupamos hoy, será un REST, que significa, en inglés, REpresentational State Transfer (Representación de Transferencia de Estado) y es una arquitectura de software diseñada para distribuir aplicaciones de red. Este término fue creado por Roy Fielding en su tesis doctoral[1] y propuso 6 restricciones o principios como base para la arquitectura REST:

  • Cliente-servidor: Son consideraciones para separar al servidor de los clientes. Esto permite a los componentes de los clientes y servidor evolucionar de forma independiente.
  • Sin estado: Stateless en inglés, implica que la comunicación entre el cliente y el servidor no debe tener estado. Esto significa que el servidor no debe recordar el estado del cliente, en su lugar, debe incluir toda la información necesaria en la solicitud para que el servidor pueda entenderla y procesarla.
  • Sistema de capas: Puede existir una cantidad de capas entre el cliente y el servidor, como cortafuegos, proxies, etc. Las capas se pueden agregar, modificar, reordenar o remover de forma transparente para mejorar la escalabilidad.
  • Caché: Las respuestas del servidor pueden ser declaradas como cacheables o no cacheables. Esto permitiría al cliente, o a sus componentes intermedios, usar una respuesta pre-almacenada (o cacheada) y reusarla para solicitudes posteriores. Esto reduce la carga en el servidor y ayuda a mejorar el desempeño.
  • Interfaz uniforme: Toda la interacción entre el cliente, el servidor y los componentes intermedios se basa en la uniformidad de su interfaz. Esto simplifica, en general, la arquitectura, ya que los componentes pueden evolucionar de forma independiente en tanto que sigan usando la misma implementación. El principio de Interfaz uniforme se subdivide, a su vez, en cuatro subprincipios o restricciones: identificación de recursos, representación de recursos, mensajes auto-descriptivos e Hipermedia como Motor de Estado de la Aplicación (llamado HATEOAS, por las siglas de Hypermedia as the Engine of Application State).
  • Código en demanda: Los clientes pueden extender su funcionalidad descargando y ejecutando código en demanda, por ejemplo, guiones de JavaScript o Java.

Aplicaciones RESTful

Cuando una aplicación se adhiere a estos principios se dice que es RESTful, pero no son restricciones estrictas, sino buenas prácticas que harán de nuestras aplicaciones escalables, visibles, portables y confiables. En teoría, es posible que una aplicación RESTful sea hecha para cualquier infraestructura de software o protocolo de transporte, aunque en la práctica, las aplicaciones RESTful aprovechan las características y ventajas de la Web y usan el protocolo HTTP.

En resumen, una aplicación es considerada RESTful si cumple con los principios de la arquitectura REST. Esto significa que:

  1. Utiliza una interfaz uniforme basada en HTTP para acceder a los recursos, utilizando métodos como GET, POST, PUT y DELETE.
  2. Representa los recursos mediante un estado único, que puede ser transmitido a través de una solicitud HTTP.
  3. No mantiene un estado persistente entre las solicitudes, lo que significa que cada solicitud debe contener toda la información necesaria para completarla.
  4. Los recursos son cachéables para mejorar el rendimiento.
  5. Está diseñada utilizando un sistema de capas, lo que permite la separación de preocupaciones y la escalabilidad.

Control de PUSINEX

Los PUSINEX son planos de secciones electorales que contienen números exteriores, un trabajo muy importante para localizar ciudadanos que implica recorrer todas las manzanas de una sección y tomar de forma aproximada los números exteriores de las viviendas.

Existen muchas razones por las que un número exterior se actualiza, aunque este fenómeno es menos frecuente en las grandes ciudades. Sin embargo, es importante mantener un registro histórico de los cambios.

Esta aplicación, del lado del servidor controlará estas actualizaciones históricas y permitirá entregar a los usuarios los planos de una localidad, de una sección electoral, de un municipio o de toda la entidad.

Para empezar, utiliza Django y Django REST Framework o DRF para crear la API RESTful que será consumida por la aplicación para el usuario.

Consta de muy pocos modelos, pero vamos a revisar dos de los más importantes: Localidad y Pusinex, el primero contiene las relaciones a los modelos de Municipio y Sección y el segundo, es el histórico de los planos, que se relaciona con Localidad y Sección, ya que solo puede haber un PUSINEX por sección y localidad.

Veamos primero Localidad:

class Localidad(models.Model):
    entidad = models.PositiveSmallIntegerField(default=29, choices=ENTIDAD)
    municipio = models.ForeignKey(Municipio, on_delete=models.CASCADE)
    localidad = models.PositiveSmallIntegerField()
    nombre = models.TextField(max_length=150)
    tipo = models.PositiveSmallIntegerField(choices=CAT_TIPO)
    cabecera = models.PositiveSmallIntegerField(choices=CAT_CABECERA, null=True)

    class Meta:
        verbose_name = 'Localidad'
        verbose_name_plural = 'Localidades'

    def __str__(self):
        return f'{self.municipio.municipio:03} {self.localidad:04} {self.nombre}'

Este modelo, primero se debe serializar y de-serializar a su representación json, usando el serializador de modelos que proporciona DRF.

class LocalidadSerializer(serializers.ModelSerializer):

    class Meta:
        model = Localidad
        fields = '__all__'
        depth = 2

Y por último se debe generar la vista serializada, con un ViewSet que también proporciona DRF.

El modelo Pusinex controla las actualizaciones con el campo f_actual que permite usar la propiedad get_latest_by que nos devuelve el plano más actual.

class Pusinex(models.Model):
    seccion = models.ForeignKey(Seccion, on_delete=models.CASCADE)
    localidad = models.ForeignKey(Localidad, on_delete=models.CASCADE)
    f_actual = models.DateField('Fecha de Actualización')
    hojas = models.PositiveSmallIntegerField()
    observaciones = models.TextField()
    archivo = models.FileField(upload_to='media')

    class Meta:
        verbose_name = 'PUSINEX'
        verbose_name_plural = 'PUSINEXs'
        get_latest_by = 'f_actual'

    def __str__(self):
        return f'{self.seccion.distrito:02} {self.seccion.seccion:04} {self.localidad.localidad:04} {self.localidad.nombre} ({self.f_actual})'

Las relaciones con los modelos Localidad y Seccion permiten recuperar desde estos modelos los PUSINEX que se refieran a estas ubicaciones, y a través de la relación de Localidad con Municipio, podemos buscar PUSINEX por esta demarcación.

Crear un aplicación RESTful, se vuelve muy fácil, ya que DRF permite incluso crear los endpoint de una forma simple:

from rest_framework import routers
from views import (
    MunicipioViewSet,
    LocalidadViewSet,
    SeccionViewSet,
    PusinexViewSet
)

router = routers.SimpleRouter()

router.register(r'municipio', MunicipioViewSet)
router.register(r'seccion', SeccionViewSet)
router.register(r'localidad', LocalidadViewSet)
router.register(r'pusinex', PusinexViewSet)

urlpatterns = router.urls

Y hasta aquí dejamos este artículo, para hablar en el siguiente de cómo cumple con los principios de una aplicación RESTful.


  1. https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm ↩︎