Lección 3.4 Creando nuestra primera Query con GraphQL

Dom 21 Jun 2020 | Por: Roylan Suarez

Hola amigos lectores de CódigoJS, hoy les traigo una nueva lección de GraphQL con Django, aprenderemos a realizar la primara Query y obtener datos desde el servidor.

Primer esquema de datos

Los primero que vamos haces es crear un archivo llamado schema,py en la carpeta tareas, en el cual vamos a crear todo el esquema de datos que queremos devolver a través de la API. Para los que han trabajado con REST esto es algo parecido a un serializer.

En GraphQL, un Tipo (Type) es un objeto que puede contener múltiples campos (fields). Cada campo se calcula a través de los resolvers, los cuales devuelven un valor. Una colección de tipos (types) se llama esquema (schema) y cada schema tiene un tipo especial llamado Query para obtener datos del servidor.

Vamos analizar este schema por puntos.

import graphene

from graphene_django.types  import DjangoObjectType
from django.contrib.auth.models import User

from .models import Tarea, Comentario

class TareaType(DjangoObjectType):
    class Meta:
        model = Tarea

class Query(object):
    tarea = graphene.Field(TareaType, id=graphene.Int())
    lista_tareas = graphene.List(TareaType)

    def resolve_lista_tareas(self, info, **kwargs):
        return Tarea.objects.all()  

    def resolve_tarea(self, info, id):
               
        if id is not None:
            return Tarea.objects.get(pk=id)   
                     
        return None
  • Importamos graphene y DjangoObjectType
  • Importamos además los modelos Tarea y Comentario de nuestra app Tareas que es desde donde vamos a obtener los datos.
  • Creamos una clase llamada TareaType que hereda de DjangoObjectType:
    • Por convención esta clase debe de tener el nombre del modelo mas Type.
    • DjangoObjectType por defecto, presentará todos los campos en un modelo a traves de GraphQL. Si solo deseas que esté presente un subconjunto de campos, puedes hacerlo utilizando field o exclude. En nuestro ejemplo utilizaremos todos los campos.
  • Definimos en el Meta el modelo que vamos a utilizar, en este caso Tarea.
  • Seguido vamos a declarar la clase Query y crear un listado de tareas a través del graphne.List, al cual le pasamos TareaType que, como vimos, representa el modelo con los datos que vamos a consultar.
  • Por último, creamos un resolver el cual nos va a devolver los datos y que deben tener el siguiente formato:
def resolve_foo(self, info, **kwargs):

Donde foo es nombre del campo declarado en el objecto Query de tipo List.

Ahora, necesitamos hacer una modificación en el esquema principal, el que creamos en la lección anterior, para ello editamos el archivo schema.py que está en la carpeta backend y lo modificamos como está a continuación.

import graphene

from tareas.schema import Query as TodoSchemeQuery

class Query(TodoSchemeQuery, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query)

Aquí, lo que hemos hecho es importar el schema.py de la app tareas en el esquema principal que es el punto de entrada de GraphQL en Django.

Por ahora es suficiente, si has seguido este tutorial al pie de la letra ya puedes ejecutar la primera consulta.

Nos vamos al navegador y abrimos la consola de graphiql http://localhost:8000/graphql. La consola de GraphQL es fantástica porque nos permite hacer todo tipo de consultas en desarrollo para asegurarnos de que todo funciona bien.

Primera consulta

Vamos a ver como realizamos nuestra primera consulta, pero antes vamos entender la consola de GraphQL.

Consola de GraphQL

  • En la sección de la izquierda es donde vamos a escribir nuestras consultas.
  • En el centro es donde se mostraran los resultados de nuestras consultas.
  • A la derecha podemos consultar todos los tipos de esquemas que tenemos declarados y que voy a explicar un poco en detalle:
    • Como vemos en la imagen, si hacemos clic en Query veremos todos los querys que hemos declarado en nuestro schema.py, en este caso, solo veremos listaTareas y si seguimos haciendo clic veremos todos los campos que tiene nuestro esquema con su descripción:

Query Type GraphQL

Lo cual es fantástico porque si el modelo está bien documentado podremos realizar nuestras consultas sin tener que movernos de la consola.

Ahora sí, vamos a lo que nos gusta a los desarrolladores, escribir código (laugh):

La consola de GraphQL, por si fuera poco lo que hemos visto, autocompleta código, en la parte superior escribimos la palabra query, verás que con solo escribir la letra q nos va a sugerir la palabra, seguido escribimos dos llaves.

query {

}

Entre las dos llaves, presionamos la tecla Ctrl + Espacio y saldrá el autocomplete, el cual nos mostrará los query que tenemos declarados, es este caso listaTareas, lo seleccionamos y nuevamente escribimos dos llaves {}

query {
   listaTareas {
     
  }
}

Nuevamente presionamos Ctrl + Espacio y el autocomplete nos mostrará todos los campos disponibles, seleccionamos uno por línea

query {
  listaTareas {
    id
    nombre
    descripcion
  }
}

Y listo, ahora precionamos Ctrl + Enter y veremos el resultado, ufff, pero no ha mostrado nada, claro, porque no tenemos datos en nuestros modelos:

{
  "data": {
    "listaTareas": []
  }
}

Nos vamos al admin de Django y creamos dos tareas, en mi caso Tarea 1 y Tarea 2. Volvemos a la consola y ejecutamos la consulta con Ctrl + Enter y ahora veremos el resultado tan esperado.

{
  "data": {
    "listaTareas": [
      {
        "id": "2",
        "nombre": "Tarea 1",
        "descripcion": "Descripcion tarea 1"
      },
      {
        "id": "3",
        "nombre": "Tarea 2",
        "descripcion": "Descripcion tarea 2"
      }
    ]
  }
}

Fácil, verdad…

Mostrando datos relacionados

Vamos a suponer que necesitamos mostrar los comentarios de cada tarea, si nos fijamos en los modelos estos están relacionados:

tarea = models.ForeignKey(Tarea, on_delete=models.CASCADE)

¿Entonces cómo mostramos los comentarios de cada tarea? Vamos a la consola e insertamos un campo debajo de descripción y presionamos Ctrl + Enter, seleccionamos comentarioSet abrimos y cerramos llaves y escribimos los campos que queremos devolver en la consulta:

query{
	listaTareas {
    id
    nombre
    descripcion
    comentarioSet {
      id
      comentario
    }
  }
}

Ejecutamos la consulta y, como no tenemos comentarios en la base de datos, no tendremos resultados, pero nuevamente nos vamos al admin de Django y añadimos varios comentarios a la Tarea 1 y ejecutamos la consulta, el resultado debería de ser como el siguiente:

{
  "data": {
    "listaTareas": [
      {
        "id": "2",
        "nombre": "Tarea 1",
        "descripcion": "Descripcion tarea 1",
        "comentarioSet": [
          {
            "id": "2",
            "comentario": "Comentario 1"
          },
          {
            "id": "3",
            "comentario": "Comentario 2"
          }
        ]
      },
      {
        "id": "3",
        "nombre": "Tarea 2",
        "descripcion": "Descripcion tarea 2",
        "comentarioSet": []
      }
    ]
  }
}

Más fácil imposible…

Mostrando detalles de una consulta

Una tarea muy común es ver los detalles de un registro de la base de datos, por ejemplo, queremos ver los detalles de una tarea determinada. ¿Cómo lo hacemos?

En la clase Query añadimos un nuevo campo de tipo Field

tarea = graphene.Field(TareaType, id=graphene.Int())

Al cual le pasarmos como argumentos un campo adicional:
    • id: que será de tipo Integer

Ahora, creamos un resolve de tarea de la siguiente forma:

def resolve_tarea(self, info, id):
    if id is not None:
        return Tarea.objects.get(pk=id)   
        
    return None

Recuerda, los resolve siempre deben nombrarse con la palabra resolve_ y el nombre del campo declarado, en este caso tarea (resolve_tarea)
En la función comprobamos si existe el parámetro y creamos una consulta para obtener la tarea con el ID pasado como parámetro.

Ahora, nos vamos a la consola de GraphQL a probar la nueva consulta. Limpiamos la consola y escribimos lo siguiente:

query{
    tarea(id: 3) {
    nombre
    descripcion
  }
}

De esta forma, estamos haciendo una consulta a la cual le estamos pasando entre paréntesis el id de la tarea que queremos devolver y que, además, nos devuelva el nombre y la descripción de la tarea. Presionamos Ctrl + Enter y podemos ver el resultado de la consulta.

Conclusiones

Hemos visto cómo crear Querys de diferentes tipos, los ejemplos son muy básicos pero son un punto de partida para continuar explotando esta magnifica librería.

Si quieres aprender más sobre Graphene y Django-GraphQL visita la doc oficial. Si tienes dudas y/o quieres aportar algo al post, serás bienvenido en los comentarios.

Por último, recuerda que el código fuente de este proyecto está en GitHub.

En la próxima lección hablaremos sobre los Mutations, la forma de enviar información al servidor.

Nos vemos el próximo domingo.

 



Déjanos un comentario

Artículos relacionados