Slide 1

Slide 1 text

USING GRAPHQL WITH DJANGO MARTIN BROCHHAUS

Slide 2

Slide 2 text

WHOAMI ▸ Martin Brochhaus ▸ CTO of The Artling ▸ Founder of Bitlab Studio ▸ @mbrochh ▸ martin@theartling.com ▸ martin.brochhaus@bitlabstudio.com 2

Slide 3

Slide 3 text

▸ 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

Slide 4

Slide 4 text

▸ 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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

TRY YOUR FIRST GRAPHQL QUERY ▸ Browse to http://0.0.0.0:8000 13

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

LET’S HAVE A QUICK LOOK AT THE FRONTEND AND SEE WHY THIS IS AWESOME 15

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

18

Slide 19

Slide 19 text

Querying is cool, but what about filtering? You can use the powerful `django-filter` module for this! 19

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

TRY IT OUT IN GRAPHIQL ▸ You can now filter on the `message` field: 21

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

TRY IT OUT IN GRAPHIQL ▸ You can now create new messages ▸ The result of the mutation can be treated like another Query 26

Slide 27

Slide 27 text

Alright, I’m convinced, how can I join the Revolution?! thearlting.com is hiring, talk to me after the meet up ;-) 27

Slide 28

Slide 28 text

THANK YOU FOR LISTENING! Martin Brochhaus CTO of The Artling @mbrochh