Binary Coffee

Creando una API con Django y Graphene

django graphql graphene python
En este tutorial crearemos una simple API GraphQL utilizando Django y Graphene. **GraphQL** permite al cliente decidir qu√© datos pedir al servidor, lo que quiere decir que, si se necesitara informaci√≥n adicional, o si simplemente deja de necesitar un dato, no tiene que modificar el backend solamente la query **GQL**. ## Diferencias con REST Una de las principales diferencias con **Rest** es la forma de interactuar con la **API**. **Rest** empieza con una petici√≥n HTTP que hacemos usando alguno de los m√©todos, **GET**, **POST**, **PUT**, **PATCH** o **DELETE**, a determinadas **URL** √ļnicas por recurso del **API**. Por ejemplo, haciendo una petici√≥n **GET** a `/api/posts/`, obtenemos una lista de todos los posts. Si en cambio la hacemos a `/api/posts/:id`, podemos pedir datos de un art√≠culo espec√≠fico. Con **POST** podemos crear nuevas entradas. **PUT**, **PATCH** y **DELETE** nos sirve para actualizar y borrar. En cambio con **GQL** tenemos un solo endpoint, por lo general `/graphql`, y solo interactuamos con √©l mediante el m√©todo **POST**. Para decirle que datos queremos crear, modificar u obtener colocamos en el cuerpo de la petici√≥n: * **Query** * **Mutation** * ***Subscription*** (*Este lo veremos en otro art√≠culo*) Estas son las 3 formas de interactuar con un **API GraphQL**. M√°s adelante vamos a ver de qu√© se trata cada una. Ahora necesitamos crear el proyecto. ## Creando el proyecto Lo primero que debemos hacer es crear un proyecto con Django, para ello ejecutamos en la consola: ``` $ mkdir proyecto $ cd proyecto $ virtualenv -p python3 env $ source env/bin/activate $ pip install django $ pip install graphene_django $ django-admin startproject faseslibros $ cd faseslibros $ django-admin startapp core ``` Si no sabes lo que un entorno virtual puedes ver el art√≠culo [C√≥mo instalar Python y crear entornos virtuales](https://binary-coffee.dev/post/como-instalar-python-y-crear-entornos-virtuales). Ahora debemos aplicar las migraciones para reflejar las tablas que utiliza Django en la base de datos. ``` $ python manage.py migrate ``` Definimos nuestro modelo Autor. ``` # fraseslibros/core/models.py from django.db import models class Autor(models.Model): nombre = models.CharField(max_length=100) def __str__(self): return self.nombre ``` Agregamos `core` a las aplicaciones instaladas. ``` # settings.py INSTALLED_APPS = [ ... 'core', ] ``` Corremos nuevamente las migraciones para que los modelos se reflejen en la base de datos. ``` $ python manage.py makemigrations $ python manage.py migrate ``` Registramos nuestros modelos en `core/admin.py`, esto har√° que sean visibles en la administraci√≥n. ``` from django.contrib import admin from .models import Autor admin.site.register(Autor) ``` Debemos crearnos un usuario, ejecutamos en la consola y completamos los campos: ``` $ python manage.py createsuperuser ``` Levantamos el servidor y creamos algunos datos en la [administraci√≥n](http://localhost:8000/admin). ``` $ python manage.py runserver ``` Por defecto el servidor se ejecuta en el puerto 8000, aunque se puede cambiar. ``` $ python manage.py runserver 3155 ``` Tambi√©n podemos adicionar datos desde la consola: ``` $ python3 manage.py shell >>> from core.models import Autor >>> Autor.objects.create(nombre='Pedro Betancourt') >>> Autor.objects.create(nombre='Francisco Jos√©') ``` ## Graphene Schema El **schema** es donde se van a registrar todos las acciones de nuestra **API**, ya sean **Query**, **Mutation**, o **Subscription**, aunque este √ļltimo lo veremos en otro art√≠culo. Se acostumbra a crear un `schema` global, o sea de todo el proyecto y otros en cada una de nuestras apps a modo de organizaci√≥n. ### Query Una **Query** b√°sicamente es una consulta que hacemos a nuestra **API**. Vamos a crear el archivo `core/schema.py`. Para ello debemos crear dos clases, `AutorType` que permite a **GraphQL** utilizar nuestro modelo `Autor` y la clase `Query` que es donde registramos las consultas. ``` from .models import Autor from graphene_django.types import DjangoObjectType from graphene import ObjectType import graphene class AutorType(DjangoObjectType): class Meta: model = Autor class Query(ObjectType): autores = graphene.List(AutorType) def resolve_autores(self, info, **kwargs): return Autor.objects.all() class Mutation(graphene.ObjectType): pass ``` Ahora creamos nuestro schema global en `fraseslibros/schema.py`, que b√°sicamente lo que hace es coleccionar las acciones del resto de los schemas: ``` import core.schema import graphene class Query(core.schema.Query, graphene.ObjectType): pass class Mutation(core.schema.Mutation, graphene.ObjectType): pass schema = graphene.Schema(query=Query, mutation=Mutation) ``` Agregamos **Graphene** a las aplicaciones instaladas: ``` INSTALLED_APPS = [ ... 'core', 'graphene_django', ] ``` Especificamos cu√°l ser√° nuestro **schema** principal en `fraseslibros/settings.py`: ``` GRAPHENE = { 'SCHEMA': 'fraseslibros.schema.schema', } ``` Registramos nuestro cliente **GraphQL** en `fraseslibros/urls.py`. ``` from django.contrib import admin from django.urls import path from graphene_django.views import GraphQLView from django.views.decorators.csrf import csrf_exempt admin.autodiscover() urlpatterns = [ path('admin/', admin.site.urls), path('graphql/',csrf_exempt(GraphQLView.as_view(graphiql=True))), ] ``` Ahora podemos dirigirnos a http://127.0.0.1:8000/graphql/ y ver√°n el cliente corriendo. Es importante que est√©s conectado a internet la primera vez porque carga contenido externo, algunos estilos y scripts, pero solo lo hace una vez. #### Probando Ahora ejecutamos en el cliente GraphiQL la siguiente `query`: ``` query{ autores{ id, nombre } } ``` Y deber√≠amos recibir como respuesta un **JSON** con los datos que creaste anteriormente: ``` { "data": { "autores": [ { "id": "1", "nombre": "Raul C. Rivero" }, { "id": "2", "nombre": "Francisco" } ] } } ``` ### Mutation Las queries nos permiten obtener datos, pero se necesita una forma de crear, modificar, eliminar o interactuar con estos datos. Estas acciones son llamadas mutaciones. Una mutaci√≥n es similar a una funci√≥n: recibe ciertos par√°metros, realiza un cambio y devuelve una respuesta. Para registrar nuestras mutaciones nos dirigimos nuevamente a `core/schema.py` y creamos `AutorMutation` que se encargar√° de crear nuevos autores, recibe como argumento el `nombre` y retorna un `autor`. Tambi√©n lo registramos en la `class Mutation` que hab√≠amos dejado pendiente anteriormente. ``` class AutorMutation(graphene.Mutation): class Arguments: nombre = graphene.String() autor = graphene.Field(AutorType) def mutate(root, info, nombre): autor = Autor.objects.create(nombre=nombre) return AutorMutation(autor=autor) class Mutation(ObjectType): crear_autor = AutorMutation.Field() ``` #### Probando Ahora ejecutamos en el cliente GraphiQL la siguiente `mutation`: ``` mutation{ crearAutor(nombre: "Elon Musk"){ autor{ id, nombre } } } ``` Deber√≠amos recibir como respuesta un **JSON** con los datos del autor creado: ``` { "data": { "crearAutor": { "autor": { "id": "6", "nombre": "Elon Musk" } } } } ``` ## A d√≥nde ir desde aqu√≠ Puedes investigar y crear autenticaciones con **JWT**, suscripciones e incluso aprender a filtrar los datos con **django_filters**. Esperamos que te gustara el art√≠culo y que pudieras entender algunas cuestiones t√©cnicas y c√≥mo implementar una **API** con **Graphene** (*Cliente de GraphQL para Django*) y **Django**. > Keep calm and drink Binary Coffee!
Opiniones
noavatar
noavatar