Pro Yearly is on sale from $80 to $50! »

Using GraphQL with Django

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

3949eadbf8213b05e415415b2c17eaee?s=128

Martin Brochhaus

June 19, 2017
Tweet

Transcript

  1. USING GRAPHQL WITH DJANGO MARTIN BROCHHAUS

  2. WHOAMI ▸ Martin Brochhaus ▸ CTO of The Artling ▸

    Founder of Bitlab Studio ▸ @mbrochh ▸ martin@theartling.com ▸ martin.brochhaus@bitlabstudio.com 2
  3. ▸ 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
  4. ▸ 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. 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
  13. TRY YOUR FIRST GRAPHQL QUERY ▸ Browse to http://0.0.0.0:8000 13

  14. 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
  15. <INTERMISSION> LET’S HAVE A QUICK LOOK AT THE FRONTEND AND

    SEE WHY THIS IS AWESOME 15
  16. 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
  17. 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
  18. </INTERMISSION> 18

  19. Querying is cool, but what about filtering? You can use

    the powerful `django-filter` module for this! 19
  20. 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
  21. TRY IT OUT IN GRAPHIQL ▸ You can now filter

    on the `message` field: 21
  22. 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
  23. 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
  24. 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
  25. 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
  26. TRY IT OUT IN GRAPHIQL ▸ You can now create

    new messages ▸ The result of the mutation can be treated like another Query 26
  27. Alright, I’m convinced, how can I join the Revolution?! thearlting.com

    is hiring, talk to me after the meet up ;-) 27
  28. THANK YOU FOR LISTENING! Martin Brochhaus CTO of The Artling

    @mbrochh