Implementando una API con GraphQL (Parte 2)
📌 Este texto forma parte de una serie de 2 artículos. Para ver la primera parte, haz CLIC AQUÍ
En el artículo anterior estuvimos analizando los principales elementos que hacen de GraphQL una de las principales tecnologías en la creación de API en la actualidad.
Para esto analizamos algunos aspectos teóricos sobre Querys y luego lo llevamos a la práctica con un ejemplo sencillo donde consultábamos los datos de nuestra base de datos mediante consultas desde la interfaz de pruebas de GraphQL.
Toda esta información se verá complementada con el artículo de hoy, en el que estaremos analizando las mutaciones y cómo se integra con un framework frontend de punta como Vue.
Entonces, comenzamos.
Mutaciones
Con el contenido del artículo anterior abarcamos los principales aspectos relacionados con la obtención de datos del servidor mediante peticiones desde un cliente cualquiera utilizando la sintaxis de consulta que proporcionan GraphQL mediante las Querys.
Pero la información fluye en ambos sentidos en un sistema real, y aquí es precisamente donde las mutaciones hacen su entrada.
Las mutaciones y las consultas son similares en definición, la principal diferencia reside en el uso.
En la práctica es posible realizar tareas de escritura de datos con cualquiera de estas operaciones, pero por convención todas las operaciones que modifiquen datos en el servidor deben ser enviadas a través de mutaciones.
Pasemos a la sintaxis de una mutación.
mutation CrearAutor ($usuario: String!, $nombre: String!, $apellidos: String!){ CrearAutor (usuario: $usuario, nombre: $nombre, apellido: $apellido) { success errors } }
En este ejemplo comenzamos definiendo el nombre de la mutación como CrearAutor, y declaramos los tipos de datos de cada uno de los parámetros que debe recibir.
Luego llamamos a la mutación pasándole los parámetros que recibimos arriba y solicitamos que la respuesta incluya un valor que nos diga si se ejecutó correctamente o los errores que ocurrieron en caso contrario.
Para que nuestra API responda a esta consulta debemos implementar como el servidor va a resolver la mutación.
El resultado debe ser algo como esto:
class CrearAutor(graphene.Mutation): class Arguments: usuario = graphene.String() nombre = graphene.String() apellidos = graphene.String() autor = graphene.Field(AutorType) success = graphene.Boolean(default_value=True) errors = graphene.String() @classmethod def mutate(cls, root, info, usuario, nombre, apellidos): try: autor_instance = Autor( nombre = nombre, apellidos = apellidos, usuario = usuario ) autor_instance.save() return cls(success = True, autor = autor_instance) except Exception as e: return cls(success = False, errors=str(e))
En la primera línea solamente declaramos el método, que tiene que heredar de la clase Mutation de la librería Graphene.
En la segunda línea comenzamos con la declaración de los argumentos que recibirá el método desde fuera. En este caso el usuario, nombre y apellidos del autor.
Luego definimos qué se espera como respuesta del servidor, en este caso el objeto Autor que se acaba de crear, un indicador denominado success que informa si la operación se realizó satisfactoriamente, y por último si hubo algún error en la ejecución de proceso.
Con todo el esquema creado pasamos a implementar el método mutate, el cual recibe por parámetros los datos que necesitamos, crea una instancia del Autor con ellos y la guarda en la base de datos.
Posteriormente publica la respuesta que puede ser satisfactoria o fallida, información que se enviará de vuelta al cliente que la solicitó.
En este ejemplo intenté traer una mutación muy básica para favorecer el aprendizaje de las personas que aún no tienen dominio sobre esta tecnología.
Si te interesa comenzar a trabajar con GraphQL debes revisar todas las opciones y modos de uso que brindan en su web oficial.
Ahorra en software
Únete al boletín premium semanal con los mejores lifetime deals y ofertas de software.
Implementando el cliente
Hasta este punto hemos cubierto lo básico de GraphQL, implementando en el servidor el esquema para resolver las consultas que necesitamos.
Pero esto es solo el backend, ¿cómo podemos utilizar estas funcionalidades de nuestra API desde el frontend?
Para ilustrarlo hemos elegido el framework Vue con la librería Apollo, que es uno de los mejores clientes para GraphQL que puedes encontrar para este framework.
Instalando Vue
Lo primero que debemos instalar es NodeJS para comenzar a instalar todos los demás paquetes mediante su gestor de dependencias npm. Puedes descargar NodeJS aquí.
Una vez instalado procedemos a instalar vue-cli.
Este paquete nos va a proporcionar una interfaz de líneas de comando que permitirá la creación de proyectos, probar la aplicación mientras la desarrollas, generar los ficheros JavaScript finales desde nuestros archivos de proyecto, entre otras cosas.
Para instalar este paquete debemos usar el siguiente comando en nuestro terminal:
npm install -g @vue/cli
Una vez instalador podemos proceder a crear nuestro proyecto desde nuestra consola:
vue create saasradar_front
Nos preguntará que versión de Vue queremos instalar, y en este momento escogeré la versión 2, debido a que, aunque Vue 3 ya es estable, algunos paquetes de terceros aun no son del todo compatibles.
Una vez seleccionado Vue 2 solo tenemos que esperar a que se descarguen las dependencias necesarias hasta que obtengamos algo como esto:
Ya tenemos un proyecto Vue creado. Puedes acceder si ejecutas el comando npm run serve dentro de la carpera que se creó para el proyecto como se indica en la imagen.
Y tenemos nuestra aplicación corriendo en nuestra estación de trabajo a través del puerto 8080 por defecto. Si accedemos a través de nuestro navegador web obtendremos nuestra página de inicio.
Instalando graphql y graphql-tag
Pasamos a instalar estas 2 librerías necesarias para el correcto funcionamiento de nuestro ejemplo mediante el siguiente comando:
npm install graphql graphql-tag -D
Instalando Apollo
Con Vue instalado pasamos a instalar Apollo utilizando el siguiente comando:
vue add apollo
Como se nota en la imagen en mi caso decidí no agregar código de ejemplo, servidor para la API o una configuración para el cliente desde este paso. Estas configuraciones vendrán luego.
Instalando Vuetify
Una vez instalado Apollo procedemos a instalar vuetify, que es la principal librería de componentes visuales para Vue.
vue add vuetify
Rápidamente nos preguntará que tipo de instalación deseamos, donde escogeremos la opción Default.
Instalando Vue-Router
Por último, vamos a instalar Router para manejar las rutas del lado del cliente.
vue add router
Una vez concluidas estas instalaciones ya tenemos todo lo que necesitamos para este ejemplo.
Debo aclarar que Router y Vuetify no son necesarios para consumir una API con GraphQL, pero nos van a ayudar en la visualización de los resultados.
Si abrimos nuestro proyecto con alguna herramienta de edición de código podrás ver la siguiente estructura:
Configurando Apollo
Lo primero que configuraremos será Apollo, especificándole la URL de la ruta que responderá a las consultas GraphQL. Para esto debemos abrir el fichero vue-apollo.js y modificar la constante httpEndpoint.
Si leíste el artículo anterior sobre GraphQL en este punto quizás reconozcas una de las ventajas de esta tecnología, y es precisamente la inclusión de la ruta del servidor en un único punto, algo que agradecerás mucho, sobre todo en grandes proyectos.
Configuremos nuestro cliente de Apollo en este mismo fichero, agregando el siguiente código después de la definición de las opciones por defecto:
export const { apolloClient, wsClient } = createApolloClient({ ...defaultOptions // ...options }) apolloClient.wsClient = wsClient
Quedaría así:
Configurando Rutas
Ahora vamos a darle un vistazo a las rutas por defecto de nuestra aplicación abriendo el fichero index.js dentro de la carpeta router.
Según este código, cuando se entre a la URL principal (definida por “/”) de nuestra aplicación, se mostrará el componente Home. ¿Qué hace Home?
Básicamente da alguna información de bienvenida y muestra el componente HelloWorld. Para simplificar nuestro ejemplo utilizaremos este componente, por lo que vamos a abrirlo eliminar todo su contenido y poner nuestro código.
Creando Query
Lo que haremos será crear una tabla que muestre los resultados de la consulta todos_autores que implementamos en el artículo anterior.
Entonces, crearemos una carpeta llamada graphql dentro de src para volcar nuestras consultas y mutaciones mediante 2 ficheros nombrados queries.js y mutations.js donde utilizaremos graphql-tag.
Nuestro fichero querys.js quedaría así:
import gql from 'graphql-tag' export const todos_autores = gql` query { todos_autores { id usuario nombre apellidos } } `
Creando componente Vue
Ahora modificamos el contenido del fichero Home.vue agregando el siguiente código:
<template> <v-data-table :headers="headers" :items="autores" class="elevation-1" > <template v-slot:top> <v-toolbar flat > <v-toolbar-title>Autores</v-toolbar-title> </v-toolbar> </template> </v-data-table> </template> <script> import { apolloClient } from '@/vue-apollo' import { todos_autores } from '@/graphql/queries' export default { data: () => ({ autores: [], headers: [ { text: 'Usuario', align: 'start', sortable: false, value: 'usuario', }, { text: 'Nombre', value: 'nombre' }, { text: 'Apellidos', value: 'apellidos' }, ], }), methods: { async obtenerAutores () { const resp = await apolloClient.query({ query: todos_autores }) this.autores=resp.data.todosAutores }, }, created () { this.obtenerAutores() }, } </script>
En este utilizamos el componente datatable que nos proporciona Vuetify, especificando que el origen de sus datos será la variable autores, que inicialmente es un arreglo vacío.
En la sección script del componente importamos nuestro cliente de Apollo y la consulta que definimos arriba.
Creamos un método que lleva por nombre ObtenerAutores que será el encargado de ejecutar solicitar los datos de la consulta a la API y llenar la variable autores con el resultado.
De este modo la tabla inicia vacía y se actualiza cuando los datos lleguen desde el servidor, mostrando nuestros autores.
Resultado final
La imagen muestra el resultado de la consulta, con todas las peticiones que se realizaron. Entre ellas, la que más nos interesa ahora mismo es la que se encuentra marcada.
Si te fijas puedes ver como hace la petición a la URL de la API basada en GraphQL que creamos en Django y como esta le devolvió los resultados de la consulta que el cliente ejecutó.
Nota: Al alojar cliente y servidor en la misma PC para hacer las pruebas puedes obtener un problema de CSRF, que podemos resolver con el módulo django-cors-headers.
Hasta aquí el artículo de hoy, donde intentamos abarcar todo el tema GraphQL en el cliente y el servidor de la forma más simple posible teniendo en cuenta todas las tecnologías que involucra.
Te dejo el ejemplo completo con todo el código del cliente y el servidor, cualquier duda o sugerencia la podemos ver en los comentarios.