API REST con Django y PostgreSQL
Cuando accedemos a un sitio web y queremos obtener o modificar la información que tiene almacenada en su base de datos como, por ejemplo, los datos de tu cuenta en una red social, el frontend del sitio web (que es la parte visual con la que interactuamos) realiza una solicitud al backend, donde un servidor verifica que la solicitud sea correcta, busca información en la base de datos y devuelve el resultado al cliente. Una forma de implementar dicho sistema es a través de una API REST.
En este artículo veremos en la práctica cómo diseñar este sistema usando el framework Django y la base de datos postgreSQL.
API
Una API (Application Programming Interface o, en español, Interfaz de Programación de Aplicaciones) es una forma en la que dos sistemas interactúan: el que usa la API realizará solicitudes y el que proporciona analizará estas solicitudes y devolverá la respuesta adecuada.
De esta forma, el primero podrá interactuar con el segundo sin necesidad de conocer el código del segundo, simplemente intercambiarán datos.
REST
REST (Representational State Transfer o, en español, Transferencia de Estado Representativo) es un patrón para intercambiar información entre aplicaciones a través de llamadas HTTP, por lo que los recursos de una API se organizan en varias URI únicas (abreviatura de Uniform Resources Identifiers o Identificador Uniforme de Recursos), que son strings que diferencian recursos de datos en un servidor.
Requisición
El mensaje de solicitud que el cliente envía al servidor tiene un formato muy específico: la primera línea dice el método utilizado (que puede ser, por ejemplo, GET, POST, PUT o DELETE) y, enseguida, la URI a la que queremos ingresar.
A continuación, vienen los headers que son los encabezados de requisición, donde se contienen los metadados de requisición como accept, que dice al servidor el formato aceptado de los datos; authorization, un token que permite el acesso del cliente a los datos en el servidor, entre otros. Por último, tenemos body, donde van los datos customizados que el cliente quiere enviar al servidor.
Observa el ejemplo abajo:
En él tenemos el método POST, que crea un registro, y luego la URI, que identifica la categoría del producto, el tipo de dato de comunicación que es json en accept y en el body tenemos el nombre del producto, el precio y el descuento. Este ejemplo podría usarse en el caso de un sistema de gestión de inventario donde una persona podría registrar un nuevo producto en la base de datos para que aparezca en su tienda.
Además del método POST que se usa para crear, también está el GET que se usa solo para leer un registro, el PUT para actualizar uno existente, el DELETE que eliminará un registro, entre otros.
Respuesta
El mensaje de respuesta también tiene un formato específico. La primera línea contiene el código de estado para decirle al cliente qué sucedió con la solicitud, luego vienen los headers que contendrán información sobre el servidor y finalmente el body que es el contenido, generalmente devuelto en formato json.
Observa el ejemplo abajo:
Existen varios códigos de retorno, donde los 100 representan respuestas de información, 200 representan respuestas exitosas, 300 son redireccionamientos, 400 son errores del cliente y 500 son errores del servidor.
La arquitectura REST es Stateless, lo que significa que es sin estado, es decir, cada ciclo de solicitud y respuesta es independiente entre sí y ninguna de las partes, ni el cliente ni el servidor, necesita almacenar información entre sí.
Configurando el proyecto
Entendida la parte teórica, vamos a crear un proyecto con Django. Primero, debemos generar y activar un ambiente virtual Python e instalar las bibliotecas necesarias. Digita en la terminal lo siguiente:
Hecho eso, iniciamos un proyecto Django con el nombre myproject:
Este comando creará varios archivos. Manage.py será el punto de entrada donde vamos a manejar nuestra aplicación a través de la línea de comando. Dentro de la carpeta myproject quedarán los archivos relevantes para nuestro proyecto: settings.py para configuraciones y urls.py donde colocaremos los links customizados para que el usuario ingrese en el navegador.
Para configurar la base de datos, primero es necesario que tengas instalado postgreSQL. Ingresa al site oficial e instálalo al lado de pgadmin. Hecho eso, en el archivo settings.py donde están las databases vamos a sustituir el patrón que Django genera con sqlite3 con los datos de postgres de la siguiente forma:
En lugar de name, user y password, vas a colocar el nombre de tu base de datos, tu usuario y tu contraseña. El host es el localhost, por lo que el postgres está en nuestra computadora y el puerto es, por patrón, el 5432.
El archivo settings posee información sensible. Por ende, debido a temas de seguridad, una buena práctica es crear siempre un archivo llamado .env y colocar en él la SECRET_KEY y los parámetros de la base de datos. Para eso, vamos a crear el archivo .env y, dentro de él, colocaremos cada una de esas variables con el string que contiene su valor:
Para usar estas variables, necesitamos importar la función config de la biblioteca decouple que instalamos al inicio dentro de settings.py:
Ahora solo basta pasar en el lugar del valor de cada variable la función config con el nombre de la variable que durante la ejecución va a tomar la información que está en el archivo .env:
Cuando vayas a colocar el código en un repositorio en GitHub, por ejemplo, declara el .env en el archivo .gitignore para que no sea enviado. Si trabajas con más desarrolladores, puedes añadir un archivo .env.example con el nombre de las variables y los valores falsos para que los demás sepan cuáles variables necesitan ser declaradas para que el código funcione.
En el archivo settings.py, en INSTALLED_APPS vamos a añadir ‘rest_framework’ para configurar la biblioteca que utilizaremos para crear la API REST:
Ahora crearemos una carpeta llamada api con un archivo __init__.py vacío, así como un archivo llamado views.py y otro con el nombre de urls.py. En views.py importaremos la función response y api_view de la biblioteca djangorestframework:
A continuación, crearemos la función que va a devolver los datos. En el decorator colocaremos el método de requisición que, en este caso, será GET y va a recibir como parámetro el request para devolver como respuesta un diccionario:
Dentro del archivo urls.py importaremos la función path de Django urls, el módulo views y crearemos una lista llamada urlpatterns con la función path con el camino inicial, así como la función getData generada en views:
Acto seguido, importamos la función include do Django urls dentro del archivo urls.py de la carpeta myproject y añadir las urls de la api dentro de urlpatterns:
Con esto, basta ejecutar el comando para iniciar el servidor y acceder al localhost con el puerto 8000 (127.0.0.1:8000):
Si todo salió bien, deberías observar los datos colocados en el diccionario en el navegador, lo que significa que el sistema ya está funcionando como se esperaba. Ahora, la última parte es conectar la base de datos al sistema y crear una función para manejar una solicitud POST. Para hacer esto, comencemos creando una aplicación Django, a la que llamaremos myapp con lo siguiente:
Cuando se crea la aplicación, debemos agregarla a la lista de aplicaciones instaladas dentro del archivo settings.py del proyecto:
Luego, dentro del archivo models.py de la aplicación, creamos el primer modelo llamado Item, que será una clase que se deriva de Model. Contendrá dos atributos, el nombre y la fecha de su creación:
La función response presente en el retorno de las funciones en el archivo views.py no es capaz de tratar con datos que provienen directamente de la base de datos, por lo que es necesario serializar los datos primero. Para eso, crearemos un archivo llamado serializers.py dentro de la carpeta api y en ella importaremos los serializadores, el modelo y luego crearemos una clase para transformar los datos:
En fields puede colocarse una lista con los campos que deseas. Para aplicar todos, solo basta insertar ‘__all__’.
En el archivo views.py de la api vamos a importar el modelo, el serializer y sustituir el diccionario en la función getData por el modelo de base de datos:
Ahora simplemente ejecuta los siguientes comandos en la terminal para aplicar las modificaciones a la base de datos:
En este punto, la aplicación ya está funcionando, pero aún no tenemos datos en la base de datos para visualizar, así que codifiquemos una función más para crear los datos. Dentro de views.py de la API, la función recibirá el método POST en el decorator, serializará los datos, verificará si son válidos y guardará:
Luego, simplemente pasa esta nueva función a una URL dentro de la lista de URL en urls.py de la API:
Ahora volvemos a ejecutar el servidor y cuando accedemos a 127.0.0.1:8000/add/ podemos crear un nuevo registro en la base de datos enviando una solicitud POST. El campo que tiene un tipo de medio lo dejas como application/json y en content pones los datos en formato json (establecer clave y valor con comillas dobles):
Al acceder a la página inicial con el método GET, verás que los datos que acabamos de crear se devuelven desde la base de datos.
Conclusión
Gracias a la facilidad que brindan las librerías y el framework Django, pudimos configurar el backend para crear una API en cuestión de minutos. Desde este punto, puede modificar el archivo models.py de la aplicación para agregar más modelos a la base de datos, crear nuevas vistas en la API y URL para acceder y modificar estos datos (recordando serializar los datos antes de devolverlos).
Aún quedan varios temas que se deben tratar, como la posibilidad de crear un sistema de registro de usuarios, cómo guardar las contraseñas de los usuarios de forma segura en el banco, cómo administrar los permisos de cada usuario, realizar pruebas y tratar errores, entre otros, pero con el proyecto que hemos desarrollado en este artículo ya es posible tener un punto de partida.
¡Éxito!
Listopro Community da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.