Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Real World Graphene

Real World Graphene

Graphene is currently the most popular framework for building a GraphQL in Python and it’s also an obvious choice for adding a GraphQL layer to Django applications. Over the course of a year, we successfully built an API with about 50 queries and over 100 mutations on top of existing Django project (Saleor), but we also learned some hard lessons and had to overcome several shortcomings of the framework along the way.

In this talk, I’d like to share some practical tips to overcome the most common problems that a Django developer might face when building an optimized and maintainable API with Graphene, such as: - using useful abstractions to build queries and mutations faster - optimizing database queries in a graph - structuring a large Graphene project - unified error handling

I’d also like to bring up a few limitations of the framework that we discovered as we were working on the project and then end the talk with the most important benefits that adoption of GraphQL brings to modern web applications development - both for the backend and frontend.

Marcin Gębala

August 17, 2019
Tweet

More Decks by Marcin Gębala

Other Decks in Programming

Transcript

  1. PyCon Korea 2019 Real World Graphene Lessons learned from building

    a GraphQL API on top of a large Django project @maarcingebala
  2. ▪ Python developer at Mirumee Software & development lead at

    Saleor ▪ Building and maintaining a GraphQL API for the last two years ▪ Managing the open-source community at Saleor Who I am
  3. ▪ Basic concepts of GraphQL & Graphene ▪ Saleor -

    our journey with GraphQL ▪ Graphene: lessons learned ▪ Problems & limitations Agenda
  4. ▪ GraphQL is a data query language ▪ Developed by

    Facebook in 2012, open-sourced in 2015, managed by Linux Foundation since 2018. ▪ Alternative to REST ▪ Goals: ◦ minimize amounts of data transferred (data overfetching / underfetching) ◦ increase developer productivity ▪ In 2019, GraphQL is a megatrend. A bit of history
  5. Queries - fetching data Mutations - modifying data on the

    server Subscriptions - real-time data exchange over websockets ▪ Client decides what data to return from the server. ▪ All operations are sent as POST requests. ▪ There is only one API endpoint: /graphql. Operations
  6. Schema Definition Language Schema is a strongly typed contract between

    backend and frontend. It decouples client’s logic from server’s logic by defining data structures and operations available in API. Type definitions Operation definitions
  7. JSON response from the server - only requested fields Queries

    allow fetching data from the server. Fetching data by the client Queries
  8. ▪ Building schema using Python classes (code-first approach) ▪ Support

    for various web frameworks (Django, Flask, Tornado) ▪ Almost 5000 stars on Github Graphene https://graphene-python.org https://github.com/graphql-python
  9. Graphene Django A type created from a Django model Query

    to fetch all users from the database
  10. ▪ 50 queries and 200 mutations ▪ Authentication & permissions

    ▪ Filtering, sorting, search Saleor GraphQL API - summary Public demo: demo.getsaleor.com/graphql
  11. ▪ types.py - definitions of Graphene types, mapping models to

    types ▪ resolvers.py - resolver functions for queries ▪ mutations.py - definitions of mutation classes ▪ schema.py - gathers all types, queries, and mutations and exposes the part of schema specific for this module Project structure
  12. Using JSON Web Tokens to authenticate users with django-graphql-jwt. Use

    HTTP Authorization header to pass the token in subsequent requests and authorize them. Authentication
  13. Use HTTP Authorization header to pass the token in subsequent

    requests and authorize them. Authentication Mutation to generate a new token Using JSON Web Tokens to authenticate users with django-graphql-jwt.
  14. Mutation to generate a new token Response with the token

    and user data Use HTTP Authorization header to pass the token in subsequent requests and authorize them. Authentication Using JSON Web Tokens to authenticate users with django-graphql-jwt.
  15. The default implementation of mutations in Graphene has some limitations:

    ▪ no input data validation ▪ no standard for returning errors ▪ a lot of boilerplate in large APIs Mutations in Graphene
  16. Unified error handling All mutations return the same “errors” structure.

    Try to perform the mutation logic and return success response.
  17. Unified error handling All mutations return the same “errors” structure.

    Try to perform the mutation logic and return success response. Catch all validation errors and convert them to a Graphene type.
  18. Mutations to create new model instances follow the same logic.

    Unified mutations CLEAN INPUT DATA CREATE MODEL INSTANCE VALIDATE SAVE INSTANCE
  19. Unified mutations Mutations to create new model instances follow the

    same logic. CLEAN INPUT DATA CREATE MODEL INSTANCE VALIDATE SAVE INSTANCE
  20. Unified mutations Mutations to create new model instances follow the

    same logic. CLEAN INPUT DATA CREATE MODEL INSTANCE VALIDATE SAVE INSTANCE Example model mutation
  21. Client can ask for any combination of fields exposed in

    a type, but some of them are relations in the database. This may result in duplicated database queries. N+1 problem PRODUCT IMAGE * 1
  22. Client can ask for any combination of fields exposed in

    a type, but some of them are relations in the database. This may result in duplicated database queries. N+1 problem PRODUCT IMAGE * 1
  23. Client can ask for any combination of fields exposed in

    a type, but some of them are relations in the database. This may result in duplicated database queries. ▪ products(first:1) - 2 database hits ▪ products(first:20) - 21 database hits N+1 problem PRODUCT IMAGE * 1
  24. Dynamically join database tables based on fields in a query

    with decorators provided by graphene-django-optimizer. Database optimization https://docs.djangoproject.com/en/2.2/ ref/models/querysets/#select-related Uses Django’s select_related and prefetch_related methods.
  25. ▪ A fully-fledged API requires multiple additional third-party libraries on

    top of Graphene. ▪ No way to serve multiple schemas e.g. private and public API. ▪ Lack of good resources, inconsistent docs. ▪ Non-pythonic concepts in the source code. Problems and limitations
  26. ▪ GraphQL is a great tool for data exchange between

    backend and frontend and many companies are already using it. ▪ Headless architecture decouples backend and frontend and allows us to efficiently integrate our apps with other services. ▪ Graphene is the most popular code-first GraphQL framework for Python that allows for building powerful APIs. ▪ Graphene needs more support from the community. ▪ GraphQL ecosystem in Python is growing. Summary
  27. Ariadne is a Python library for implementing schema-first GraphQL servers

    that is simple to use and open for extension. ▪ Schema-first approach ▪ Support for asynchronous execution ▪ Inspired by Apollo Server Read more about schema-first vs. code-first approaches in our article “Schema-first: The Road Less Travelled”. ariadnegraphql.org Ariadne
  28. ▪ github.com/graphql-python - Graphene ecosystem ▪ flavors/django-graphql-jwt - JWT authentication

    & permissions ▪ tfoxy/graphene-django-optimizer - database optimization ▪ lmcgartland/graphene-file-upload - file upload ▪ mirumee/ariadne - schema-first GraphQL server ▪ dailymotion/tartiflette - asyncio-based GraphQL server ▪ strawberry-graphql/strawberry - GraphQL library based on dataclasses ▪ mirumee/saleor - Saleor repository, example of a large Graphene project Resources