Share
Embed
Using GraphQL with Django
Slides for a talk that I gave at the API Craft Singapore June Meetup: https://www.meetup.com/API-Craft-Singapore/events/239634405/
Code can be found here: https://github.com/mbrochh/django-graphql-demo
Video can be found here: https://engineers.sg/video/using-graphql-with-django-api-craft-singapore--1824
Martin Brochhaus
June 19, 2017
Transcript
28 slides
-
WHOAMI ▸ Martin Brochhaus ▸ CTO of The Artling ▸
Founder of Bitlab Studio ▸ @mbrochh ▸ [email protected] ▸ [email protected] 2 -
▸ graphql.org ▸ “A query language for your API” ▸
The landing page gives a very good overview over what GraphQL is ▸ Let’s have a quick look at each section… 3 -
▸ graphene-python.org ▸ “We believe that GraphQL is the next
big thing after peanut butter and REST.” ▸ Can be used with any Python application ▸ Comes with special classes for Django 4 -
Let’s create a new, empty Django project and try out
GraphQL real quick You can start using this, today! It will not touch any of your existing code and you can migrate gradually, one endpoint at a time. 5 -
INSTALL DJANGO ▸ Create a virtual environment ▸ Install Django
▸ Create new project cd ~/Projects/django-graphql-demo mkvirtualenv django-graphql-demo pip install django django-admin.py startproject graphql_demo ./manage.py migrate # add "0.0.0.0" to ALLOWED_HOSTS setting ./manage.py runserver 0.0.0.0:8000 6 -
CREATE A SIMPLE APP WITH SOME MODELS ▸ Create new
app ▸ Create a model-class (and register the admin) # file: simple_app/models.py from django.db import models class Message(models.Model): user = models.ForeignKey('auth.User') creation_date = models.DateTimeField(auto_now_add=True) message = models.TextField() 7 -
UPDATE SETTINGS & RUN MIGRATIONS ▸ Register the model with
the Django admin ▸ Add `simple_app` to `INSTALLED_APPS` setting ▸ Run `./manage.py makemigrations simple_app` ▸ Run `./manage.py migrate` ▸ Run `./manage.py runserver` ▸ Add some test data into your database via the Django admin 8 -
INSTALL DJANGO-GRAPHENE ▸ see http://docs.graphene-python.org/projects/django/en/latest/tutorial-plain/ ▸ Run: `pip install graphene-django`
▸ add `graphene_django` to `INSTALLED_APPS` setting ▸ add `GRAPHENE` setting: ▸ create Schema file for your app: code on next slide… GRAPHENE = { 'SCHEMA': 'graphql_demo.schema.schema' } 9 -
INSTALL DJANGO-GRAPHENE ▸ create Schema file for your app: #
file: simple_app/schema.py import graphene from graphene_django.types import DjangoObjectType from . import models class MessageType(DjangoObjectType): class Meta: model = models.Message class Query(graphene.AbstractType): all_messages = graphene.List(MessageType) def resolve_all_messages(self, args, context, info): return models.Message.objects.all() 10 -
INSTALL DJANGO-GRAPHENE ▸ create Schema file for your project: ▸
this consolidates all app-specific schema files into one big project- wide schema # file: graphql_demo/schema.py import graphene import simple_app.schema class Query(simple_app.schema.Query, graphene.ObjectType): pass schema = graphene.Schema(query=Query) 11 -
INSTALL DJANGO-GRAPHENE ▸ hook up GraphQL in project-URLs file ▸
this will be your only API endpoint for your application # file: graphql_demo/urls.py from django.conf.urls import url from django.contrib import admin from graphene_django.views import GraphQLView urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^graphql', GraphQLView.as_view(graphiql=True)), ] 12 -
Get it? GET IT? Our first step was to create
a Schema that describes what kind of objects can be queried and what fields are available on them. It is very similar to writing “Serializers” in Django REST Framework! 14 -
<INTERMISSION> LET’S HAVE A QUICK LOOK AT THE FRONTEND AND
SEE WHY THIS IS AWESOME 15 -
A REACT-JS COMPONENT COULD LOOK LIKE THIS: ▸ With react-apollo,
a component can define a query to fetch the data that it needs ▸ The data will be accessible via `this.props.data` ▸ Frontend engineer will use GraphiQL to figure out the queries 16 -
AN APP COULD LOOK LIKE THIS: ▸ An app is
just a composition of many custom components ▸ Each component has it’s own queries ▸ Some components might even query the same data ▸ You don’t need to worry about fetching, batching, storing, caching 17 -
Querying is cool, but what about filtering? You can use
the powerful `django-filter` module for this! 19 -
INSTALL DJANGO-FILTER ▸ Run `pip install django-filter` ▸ Change your
schema.py like this: import graphene from graphene_django.types import DjangoObjectType from graphene_django.filter.fields import DjangoFilterConnectionField from . import models class MessageType(DjangoObjectType): class Meta: model = models.Message filter_fields = {'message': ['icontains']} interfaces = (graphene.Node, ) class Query(graphene.AbstractType): all_messages = DjangoFilterConnectionField(MessageType) def resolve_all_messages(self, args, context, info): return models.Message.objects.all() 20 -
TRY IT OUT IN GRAPHIQL ▸ You can now filter
on the `message` field: 21 -
Filtering is cool, but how do I write data? Often,
you also need endpoints that write into your database. In GraphQL we call these “Mutations”. 22 -
CREATE YOUR FIRST MUTATION ▸ Add the mutation to your
app’s schema file: class CreateMessage(graphene.Mutation): class Input: message = graphene.String() form_errors = graphene.String() message = graphene.Field(lambda: MessageType) @staticmethod def mutate(root, args, context, info): if not context.user.is_authenticated(): return CreateMessage(form_errors=json.dumps('Please login!')) message = models.Message.objects.create( user=context.user, message=args.get('message')) return CreateMessage(message=message, form_errors=None) class Mutation(graphene.AbstractType): create_message = CreateMessage.Field() 23 -
HOOK UP THE MUTATION ▸ Update your project’s schema file:
import graphene import simple_app.schema class Mutation(simple_app.schema.Mutation, graphene.ObjectType): pass class Query(simple_app.schema.Query, graphene.ObjectType): pass schema = graphene.Schema(query=Query, mutation=Mutation) 24 -
MARK THE GRAPHQL ENDPOINT AS CRSF_EXEMPT ▸ Update your project’s
urls.py file: from django.conf.urls import url from django.contrib import admin from django.views.decorators.csrf import csrf_exempt from graphene_django.views import GraphQLView urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))), ] 25 -
TRY IT OUT IN GRAPHIQL ▸ You can now create
new messages ▸ The result of the mutation can be treated like another Query 26 -
Alright, I’m convinced, how can I join the Revolution?! thearlting.com
is hiring, talk to me after the meet up ;-) 27