GraphQL-first Django - Marcin Gębala

This video features Marcin Gębala at DjangoCon Europe 2020 in Online.

GraphQL-first Django - Marcin Gębala
0:41:53
Published September 30, 2020
1,222 views

DjangoCon Europe 2020 (Virtual)
September 19, 2020 - 11h15 (GMT+1)

"GraphQL-first Django" by Marcin Gębala

GraphQL is a more flexible alternative to REST for building web APIs, and thus is becoming a strong foundation for any modern web stack. This is especially true where static HTML templates are not cutting it or a sophisticated single-page interface is needed, which is often the case on the web nowadays. Even though Django was designed as a model-view-template framework, it can work perfectly well as a GraphQL server to power JavaScript apps. This talk will elaborate on the anatomy of a GraphQL-first Django application, in which GraphQL queries and mutations are the primary interfaces exposed by the backend, while the frontend remains fully dynamic.

Summary

Marcin Gębala explains how to build a GraphQL-first Django application with Graphene, using Django as an API server behind decoupled React single-page applications. He covers schema and code-first design, model-backed types, queries, mutations, authentication with JWTs, permissions, testing, data loaders for avoiding N+1 queries, and the current limitations of subscriptions. He argues that Django and Graphene provide high productivity and make it easy to expose an existing Django application through GraphQL, while warning about fragmented dependencies, weak documentation, uncertain maintenance, and the need for customizations in production; Ariadne is presented as a schema-first, more asynchronous alternative.

Key takeaways

  • GraphQL lets clients request only the fields they need, combine related resources in one request, and use a strongly typed schema as the contract between frontend and backend.
  • Graphene-Django uses a code-first approach in which Python classes, Django models, and resolvers generate the GraphQL schema.
  • Django model types, form-based mutations, and the ORM make it quick to implement queries and mutations, while JWT middleware and Django permissions handle authentication and access control.
  • Data loaders batch related-object lookups so GraphQL queries avoid the N+1 database-query problem.
  • Graphene-Django does not provide subscriptions out of the box; Django Channels and third-party libraries can add them, but support was described as experimental.
  • Django and Graphene are productive but require extra libraries and custom code, and Graphene's documentation, ecosystem maintenance, and roadmap were identified as risks; Ariadne offers a schema-first alternative with stronger asynchronous support.

Summarised automatically from the transcript.

Chapters

  1. 0:00 Introduction and Sailor Marcin Gębala introduces himself, Sailor Commerce, and its headless Django and GraphQL architecture.
  2. 2:23 GraphQL Fundamentals An overview of GraphQL queries, mutations, subscriptions, schemas, strong typing, and developer tooling.
  3. 7:31 GraphQL-First Django Architecture The talk introduces the Graphene-based architecture used to turn Django into a GraphQL server.
  4. 9:23 Project Structure and Endpoints A tour of the Django project layout, application files, schema composition, and the single GraphQL endpoint.
  5. 11:28 Types and Queries The speaker demonstrates mapping Django models to GraphQL types and defining query fields and resolvers.
  6. 15:34 Mutations and Forms This section explains Graphene mutations, validation, reusable abstractions, and form-based mutations.
  7. 19:24 Authentication and Permissions The talk covers JSON Web Token authentication and restricting GraphQL fields with Django permissions.
  8. 21:42 Database Performance and Data Loaders The speaker addresses the N+1 query problem and shows how data loaders optimize related-object access.
  9. 26:18 Testing and Subscriptions Examples cover testing GraphQL APIs with Pytest and the current options for real-time subscriptions in Django.
  10. 28:48 Graphene Tradeoffs and Alternatives The talk weighs Django and Graphene’s strengths and weaknesses before introducing the schema-first Ariadne library.
  11. 33:35 Questions Audience questions address Graphene error handling, custom GraphQL views, monitoring, and reusable Sailor abstractions.

Transcript

6,408 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:04

Hello

0:05

Speaker 1: DjangoCon Europe. Welcome to my presentation, Graphic Welfares Django. Uh my name is Martin Gambala and I'm really excited to be speaker at this year's DjangoCon. Uh I wish we were seeing each other in Portona, which is obviously not possible, but it's still really amazing that organizers were able to uh run this conference online. So this is really, really amazing. So first I'd like to tell you a few words about me and what I do. So I'm a lead developer at Sailor Commerce, where I'm responsible for leading the backend team behind the Sailor GraphQL API. I'm also a Python Django developer. I've been using those technologies for five or six years now, and I'm also a huge enthusiast of GraphQL.

0:51

Speaker 1: I've been working with this technology for about three years now, um, together with Django. So I'm based in uh Wrocław in Poland. Um Wrocław is a beautiful city in Western Poland, so whenever you have a chance to visit our country, make sure to put it on your list. And very quickly a few words about Sailor. So Sailor is an open source headless e-commerce platform. So e-commerce platform means that you can use this software to build and run online stores Um headless means that uh front end uh and back end are decoupled in this application. So it's not a uh Monolith app but front end are separate apps here which allows for um really uh great customization and flexibility

1:38

Speaker 1: uh in how you use this API So at the heart of the platform there is this GraphQL API. It's built with Django and Graphene. It's pretty large. It has over 350 operations now. And we have those two front-end apps. You can see the storefront on the right. So the storefront is a template of the online store that your customers would use to buy products. And there is also the dashboard application for store owners. So both of those apps are single page apps built with TypeScript and React and they are using our GraphQL API Uh so if you are interested, uh make sure to check it out at Sailor. io or find us on GitHub because all of that uh is open source. So uh

2:23

Speaker 1: what is GraphQL? Um GraphQL is a open source data query and manipulation language for APIs. That's the official definition I would also add to that that GraphQL is API language for single-page apps, because that's its main purpose and that's where it really shines. So let's uh take a look at GraphQL and how it looks like. So on this slide you can see example from Sailor GraphQL API. This is a interactive explorer. Almost every framework for building GraphQL servers provide uh provide this kind of explorer. So on the left we have the query. This is a query where we are getting products from the API.

3:10

Speaker 1: And for each product we are getting some fields like name, description, category and variants, for example. So as you can see, this is a nested structure And on the right we have the response. So this is a JSON response. And what is important here, we are getting only data that we have asked in the query. So this is how it looks like very quickly And now what are the main features of GraphQL? So first of all, we are fetching only data that is needed, and it is the client that decides what data to fetch. So this is very uh big difference when you compare GraphQL to REST. And the idea behind that is to limit limit amounts of data transferred from server to uh to the client.

3:58

Speaker 1: We have three types of operations in GraphQL. We have queries, which you already saw on the example before. We also have mutations and subscriptions. So mutations are equivalents of post , put or patch requests in REST APIs. So we use them to change data on the server, to create objects, update them or delete them We also have subscriptions and subscriptions are real-time queries, so we can use them to fetch data in real time. Of course they require WebSockets, so our server needs to support WebSocket connection in order to handle those subscriptions. In GraphQL we are combining multiple resources in a single request.

4:44

Speaker 1: So it's not like in REST where we have uh specific endpoints for different types of resources. In GraphQL there is only one endpoint. And as you saw on this example before, uh we have this nesting and we can use this nesting to uh traverse relations between our uh types, between our models and we can combine those types in one request. So the idea here is that a simple page app can only send one request and decide uh what data it needs to render a particular view and it doesn't uh have to hit multiple endpoints So of course there is less traffic between uh client app and the server. We also have strong typing, uh which means that every field in the API or every argument in amputation has its own type.

5:32

Speaker 1: This gives us static uh error checking uh when we write those uh queries in an editor, which is really nice. And this all leads to amazing uh developer experience, which is also one of the most important ideas in the GraphQL ecosystem. So we have those interactive IDEs to build our queries. We have API mocking. We also have code generation. And this is a very powerful feature in the frontend. Um because for example, if you are using TypeScript and if you have a really large single page app, then you should probably use TypeScript. So when you do that, you can generate your TypeScript types from the GraphQL schema. So whenever the schema changes, whenever developer's backend team adds a new field.

6:18

Speaker 1: Frontend team can just uh regenerate those types and they will instantly know that there is a new field that they need to handle. So very quickly let's uh look at the schema. Uh so schema is uh a definition of the GraphQL API. Um You can think of it as a contract between front end and back end. So here in this very simple example, we have those two special types type query and type mutation. So these are our queries and that we have in our API and here is example mutation and this is the signature. This is input data that we need to provide in order to create the product, and here we have the uh response from the mutation. As you can see, here we are defining our own type. We can use those built-in

7:04

Speaker 1: types like string, for example, to create our more complex types. And here we define the input. So in GraphQL we have two approaches, schema first and code first. Schema first means that we first create those schemas and then we build codes in our programming language to fulfill these schemas. In code first approach, on the other hand, we first build our code, our classes to represent the schema, and then the schema is generated from the code. So now I'd like to talk about this GraphQL first uh Django architecture. And the reason why I'm uh talking about this kind of architecture is that Our product, Sailor , is basically using this architecture.

7:51

Speaker 1: Fun fact is that Sailor was in the past a typical Django application with uh templates and views But after we've migrated to this headless architecture, Django is only used as the GraphQL server. So now I'd like to tell you a few aspects of this architecture. So we we're gonna use uh Graphene framework here. Uh so Graphene is a high-level framework for building GraphQL APIs in Python. You can use it standalone with Python, but it has very rich ecosystem of libraries and integrations with other frameworks such as Django or Flask. Actually, from all the GraphQL libraries in Python, I think Graphene has the best

8:36

Speaker 1: tool set for Django So also that's the reason why we are using it here. What is important here is that Graphene is also a code-first framework, which means that we are building Python classes and Python functions. And the GraphQL schema, this contract, is generated from our Python code. So let's uh look at the project structure in uh this GraphQL uh first jungle architecture. Um As you can see on the right, there is a simple example of GraphQL project that I was using while working on this presentation. Uh so maybe let's start with the uh with those files that we have in the root directory. As you can see this is pretty standard. Um uh what we have in in Django

9:23

Speaker 1: so we have settings pie for configuration and we have URL spy uh we also have WISG PI and AsDPI so that means that we are using the newest Django because of this file So this is pretty standard. What is more interesting is the architecture of a single application that we have in our Django project. So in this example I have this products app. So what do we have here? Models are pretty obvious. This is us in every Django application. In this file we define our models. So in this case we will have a product model, for example, and a category model. So this is pretty obvious. But what is different are those other files So we have types file.

10:08

Speaker 1: So here we define mappings from our models to GraphQL types. We will see that in a moment, how it looks like. Then we have mutations file where we define those operations to change data on the server for this particular application. So here we would have operations for creating products, updating or deleting them. We also have data loaders file. So data loaders are a way to efficiently run database queries in in Graphene. So we're gonna talk about that later as well. And lastly there is schema pie file. So every app in this um in this architecture would have this schema pie file. Which simply imports all the types, all mutations , and exports this schema per particular application.

10:56

Speaker 1: And then we also have this global uh this root schema file which imports all the app specific schemas. So here we measure our schemas and expose that to the GraphQL view. So this is how the project structure looks like. Now let's look at our URLs. As I said before, in GraphQL there is only one endpoint. So in our URLs, when we are starting with our application Usually we will have only this one URL. So there is this path GraphQL. We have this GraphQL view, which is provided by Graphing Django Library. And that's basically it for the URL configuration. When we hit this endpoint with a GET request in the browser,

11:43

Speaker 1: then we would see this interactive explorer that would allow us to play with the API. When we send a POST request instead, the API, this endpoint, would return the JSON data for particular query that we sent in the request body. So this is how we communicate with the API using post request. So now let's look at types. As I said in our sample application, we have the product app and we have also the product model. So now we want to expose that model in the API somehow. So how can we do that? First solution would be to write all of the type fields by hand, but Graphing

12:28

Speaker 1: Django provides us with this very nice class called Django Object Type. So we basically create our uh type as a new class that inherits from Django object type. And now let's look at this class meta here. You are probably very familiar with this concept because that's also what we do in Django. We declare that this Django object type should use the product model from our products application. Then we specify what fields we want to include in the type. This is useful because We don't want to expose all all fields automatically. We want to be sure which fields are exposed in the type. So that's why we use this only fields here

13:14

Speaker 1: And that's basically it for Graphene to create a GraphQL type based on our model. If we wanted to add uh custom fields to our type, we can easily do that as well. And we do that in a declarative manner. So this is an example of custom field. So we declare those fields here at this level. So it's very similar to declaring model fields. And for each field in our type, we also need to create a resolver. So let's look at this method here. Resolve price is a resolver function, and it will be called by graphene whenever it uh finds this field in the schema. So basically resolver uh tells the uh framework how to return data for our field

14:01

Speaker 1: So uh root uh is instance of our model uh here. So uh using this we we get the price field from the from the instance. Plus we get the currency from settings and we use that to return the money type which represents the price of a product. So now how how do we define queries? We define queries in the schema Pi file, and in this example we have only one query. So we do that very similarly. So this is a declarative style. Again, something similar to what you already saw, something similar to what we do with models. We declare that there is one query called products. It is a list of product types.

14:47

Speaker 1: As simple as that. And for that field, we also need to define a resolver function. So in this case we define the resolve products function, and as you can see we are using uh Django ORM to return all products from the database. So this is a very simple example. Of course, if you wanted to extend this query with some arguments, we could easily do that by specifying those arguments here. So we could use that pattern to for example support filtering, sorting, or pagination. And if we define an argument here, it would be available here in the resolver. So now let's talk about mutations. Mutations seem a bit more complex at first glance.

15:34

Speaker 1: So let's let's talk how how we implement them. So basically we use this graphene mutation class for that, and every mutation uh represents a single operation. For example, this one is uh used to create products So every mutation is implemented as a class. So let's look what is going on here. At the top of this implementation we define What would be the output of the mutation? So in our case, we want to return a new product instance and a list of errors that may occur during execution of the mutation Then in the class arguments we define the input. So this is data that we need to provide in order to create the product. So we've

16:20

Speaker 1: we saw that already on the schema a few slides before. I've skipped implementation of this product create input because it's very similar to what we have here. It's just a simple class with declarative fields. That match with our fields in our model. What is most important here is this mutate function. So this is basically the resolver of that mutation. So what we want to do here is to get the input data and create a new product instance. So we are doing that in this first line. Input represents the the incoming data. We populate our newly created instance with this data Then we can run some basic validation.

17:06

Speaker 1: So in this simple example I'm using uh full clean method from from Django models And of course if there are any errors like for example a field was required by but was not provided in the input, I would get a validation error here So here we are catching all those validation errors, converting them to with those small utility functions to a format that will match with the format of this output field. And if everything is fine, then we just save the newly created instance and return that to the API user. So this is how we define mutations. If you look at this code, you may think that

17:52

Speaker 1: if you have a lot of mutations to write, then probably it would be nice to use some abstractions. For example, to have the common logic for validation. So if I had a few mutations like this, I would like to have this code separated separated moved to some utility function or some mixing for example. This is easily uh this can be easily achieved because uh those mutations are classes. So we can implement those abstractions similarly as we do with uh Django uh class-based views, right? So graphene provides us with one abstraction that can be useful if you are using triangle forms. So

18:37

Speaker 1: with those, so there are uh form-based mutations. And what they do is they take a form, so let's assume that we have a model form called product form, which we can use to create new products. So if we use this Django model form mutation, which is provided by Graphene Django, we could say here that this mutation should use this form. And based on that, uh this mutation would generate for us uh input for that mutation automatically from that form. uh entire logic that would be delegated to the form and the output that would be the uh new product instas or errors, those validation errors that could happen. uh during the execution of of that mutation.

19:24

Speaker 1: So this is very useful abstraction if you want to like forms which are really nice tool provided by Django. Also, you can benefit from forms to, for example, encapsulate the validation logic in those forms. So this is very helpful abstraction if you need to build a lot of mutations like this. So now let's talk about authentication. Most app require some authentication ways and because GraphQL is designed for single page apps In single page apps, we most often use JSON Web Tokens. So if we wanted to support JSON Web Tokens in our uh Django application, our Django, uh GraphQL first Django app We need to use this library called Django

20:10

Speaker 1: GraphQL JWT. So uh JSON web tokens are not uh provided by default. Support for that is not provided by default in in Graph in Django. We need to use this library. And when we install this library, we would have, for example, this mutation in our API. This is called token create And as you can see, this mutation accepts user credentials. And when user passes those credentials and they are correct, we can ask for the access token or refresh token, for example. We can extend this mutation as well to return the user. So if we want to log them in in our single page app and immediately render the email or avatar, we can ask for this data here

20:55

Speaker 1: So once we have the token, access token, we are using this authorization header to pass this token and authenticate subsequent requests Of course, this library also provides a middleware so that our app understands how to parse those headers and how to get the user from those tokens. We can also use this library to restrict access to particular fields in our API. So let's look at this example. We have again our product type, but in this case we also have a revenue field. So uh this field should be restricted uh only to admin users with a specific permission.

21:42

Speaker 1: In this case it's uh product managed product permission. Uh we are using here standard uh Django permissions framework. Um for for those permissions. So this library gives us the permission required decorator and we can use it to decorate our resolvers. So if we add this decorator here, when the token is passed to the API, Graphene will check if the user has this permission and will only return data if they have those permissions. So uh another aspect of Graphical Effice Django is uh database performance So you probably probably heard about this N plus

22:27

Speaker 1: one problem. This is a problem that we can have in classic jungle, for example, in templates. when there is a relate relationship between our data like one to many for example. So in our case we have a product, each product can have a category and a category can have multiple products. So there is this many-to-one relationship between those models. So what we do in Django Views, we use select related or prefetch related to avoid duplicated queries, right? But this is not necessarily uh uh the best way in GraphQL because in GraphQL as you remember it is the client that decides what data to fetch. So we might get a query that only asks for

23:14

Speaker 1: product name, but we we also might get a query that asks for those categories. And we only want to run those performance improvements, though those select related uh methods, when uh user actually asks for those categories. We don't want to run them always. So we need some way to do that dynamically. We achieve that by using data loaders. So data loaders are a concept which is used in many GraphQL frameworks It originates in the or in the first implementation of GraphQL that was built in JavaScript. So maybe let's first look at how we use them and then I'll tell you how it works. So again, we have our product type. We want to return a category

24:01

Speaker 1: for this product. So without any optimization, we would simply in this resolver we would simply do root. category. Where root is our product instance, which would of course without any prefetching, that would run another database query. With data loaders, uh We use this category ID. So in our instance, we know what is the ID of the related category without fetching it from the separate table. Then we pass this ID to the data loader with the load function. And that's it. That's what we do in those resolvers. And now here is the data loader implementation. So Whenever uh so when Graphene

24:47

Speaker 1: processes this uh query, it will look uh all uh occurring the query. It will gather all the keys that we have passed here, so database IDs. And because it returns a promise, it won't immediately return the category object. Instead, it will gather all of those keys And as you can see here, we pass those keys to a uh ORM uh method here to get this data in one query. So because of those promises, uh Uh Graphene will only run that at the end of the processing that GraphQL query. So this is something new to Django developers because promises are not concept used in Python. In the next version of

25:33

Speaker 1: Graphene and hopefully in the next versions of Django, we will be able to use async await syntax here. uh in the future once asynchronous uh execution is supported in Django and database access as well. So this is synchronous code. Uh it's using those promises which are shipped with a graphene library. It's a little bit hard to understand at first. But it's relatively easy to use once you know how to how to use them. To inspect how many database queries we are actually performing, we can use the good old Django debug toolbar. So as you can see here we are running our explorer uh performing some mutations and here we can see that there are 26 queries uh in the background.

26:18

Speaker 1: We additionally need to install this Django GraphicQL debug toolbar because otherwise this debug toolbar doesn't work with those interactive uh explorers. And uh I also wanted to tell you a bit about testing, uh, so we need to make sure that uh we have all of our operations are tested. So in Sailor and in those simple examples that I'm showing here, we are using PyTest. And how can we test our API with PyTest? So this is uh definition of the query. In this case this is a mutation that we want to test. Uh it accepts some variables uh and it's just a uh multi-line string in in python.

27:03

Speaker 1: Uh so then we use this uh query uh here Uh here we define our variables for the test. And there is a little bit modified uh APA client uh which has the PostgraphQL uh method. Uh this is something that we built uh in our system. It's very simple implementation of the of the classic uh PyTest client that allows you to to query your your server And we just pass this query here and check if we get data that we expected. As a bonus, I wanted to show you real-time queries. So these are those subscriptions that we have in GraphQL. We are getting some data in real time. In the query here we are using the keyword subscription.

27:52

Speaker 1: And here we are getting feed of some messages. Is can we uh implement those subscriptions in Django? Uh unfortunately the answer for now is that Django Graph Graphene Django doesn't support subscriptions out of the box And the reason is that there is no ask eview or consumer to process WebSocket requests. So there is ongoing work on adding support for subscriptions. So we may have that in the future. For now we can use third-party libraries. So it is possible to add uh subscriptions to Django, but we need uh to use Django channels So those two libraries uh rely on channels. To be honest, I haven't used them much. Uh

28:37

Speaker 1: I know they are uh you can uh implement subscriptions with them, but I would say it's still something a little bit experimental. So I think we need to wait. uh until async uh support is is uh is provided by Django and Graphene. So is Django a good choice for a GraphQL server? So first of all, uh for me Django uh is a is productivity. Uh I love how Django provides uh very useful tools like Migrations framework, which is really amazing, ORM, which is really easy to use and very powerful, and all of the utilities that you have in Django. So I always thought that with Django you can build stuff very fast

29:22

Speaker 1: And if you use that with graphene and those code first approach when you generate types from uh from from models. I think that you can progress very fast with building your application. So I think that's very very big advantage of this tag. If you are using Graphene, you will uh see a lot of familiar concepts Such as object types, form-based mutations, and this all of them are using this declarative style, which is very familiar to Django developers because this is how we use models, for example. What is also important here is that it's relatively easy to add GraphQL API to an existing Django app. So if you already have a Django app. It's pretty easy to write those

30:08

Speaker 1: object types to map your models to a query. And if you want to experiment with the GraphQL API, it's relatively easy to do with Django and Graphene is and as an example, uh you may want to take a look at Sailor GraphQL API, which is entirely open source, and you can find that on git on GitHub. If you want to see how we implemented some particular features, you can look at the source code. This project is three years old now, this GraphQL API in Sailor and it's used in production. Also, there are some cons here. So, first of all, fully fledged server requires many additional libraries, uh which are not always well maintained. So as you saw, we need to use additional library for JSON Web Tokens. There are also libraries for file upload, for some abstractions and utilities.

30:55

Speaker 1: So there are many, many libraries that are in this ecosystem. And some of them are not really well in my opinion. Some of them are rather small packages. So if you want to use that in production, there is always this small risk that whenever a new version of graphene comes out Some packages may be behind, so there is always this risk. So it's not like in Django Rest framework when where a lot of functionality is provided by the framework itself Another disadvantage of of graphene and this this stack is that there is not much uh not many good learning resources. Unfortunately, documentation of graphene is not the best one. When you stumble upon some uh troubles, some harder

31:41

Speaker 1: problems. you often need to read the source code, which is also not the easiest one to read, the source code of graphene, I mean. So definitely uh yeah, you need to spend some time if you if you have some difficult problems with with implementation. Also, the roadmap of graphene is a little bit uncertain. There is a new version coming, but it's I'm not sure if there is any release date, and I'm not sure if all of the features will be supported. There are some features missing in the uh in graphene that are available in other implementations of of GraphQL servers in other languages. So do we have any other options? Yes there are other libraries. For example Ariadne This is a completely different philosophy because Ariadne is a schema first

32:28

Speaker 1: library. So in this library we first build the schema, then we build the Python functions to fulfill the schema. But uh it's really useful when you want to use subscriptions because it's fully asynchronous, it has first class support for those subscriptions. It provides Whiskey and ASGI views for Django. So it's there are no those mappings from models to types, for example, you need to build them by hand. But still you can use that with Django as well. What is very nice about this package is that it has very active community on spectrum. Actually, currently this one is the second most popular after graphene when you look at GitHub stars. So that's that's all I've got for you. I hope you enjoyed the presentation. If you have any questions, I'll be available on Slack

33:16

Speaker 1: You can also, I think we have still some time for questions now. You can also find me on Twitter or email me. Thanks a lot.

33:35

Speaker 2: Big problem for me Oh. Uh and the one big problem uh I had uh was like some some of my logic words in separate uh functions because I wanted to like so my business logic to be somewhere else not in the uh objects. And it made it very difficult to debug because graphene just doesn't let uh the error to be thrown. So it never gave gave me uh 500, for example So it it captures their errors and uh I get the result saying uh there's uh error in that line. Uh But it it doesn't even say

34:22

Speaker 2: uh which file it is in. So it says, well, there's a error in line 10 and I'm what okay, cool, but in line 10 of like which which file. So it made me really really uh hard to debug because like there's a type error but where in my logic there's a type error. Uh so I don't know if I was just doing something Wrong or if there's a solution for that?

34:50

Speaker 1: Actually there so I think it's a problem in Graphene in the default implementation of the GraphQL view But what we did in our project that we used in production we created our own version of that view, basically overridden it. And I'm just trying to look at where do we have it in the code but There is a way to uh write your own uh error handler or something like that. So basically the default one, as you say, catch all the errors and it's not very useful Uh I need to find that in the code. Uh give me one second, but I'm pretty sure that we need to we needed to customize it a little bit. Actually we are using graphene but uh we have

35:36

Speaker 1: a lot of small customizations here and there and this is one example. Um to to handle errors. So yeah, I agree. That's in the default implementation of gra of graphene it's it's not the best one. Um actually wait a second I can probably send you a link to make sure some links in this uh call. I don't know. Uh

36:02

Speaker 2: there's a chat here. But I think Slack would uh work too.

36:08

Speaker 1: Yeah, yeah. So maybe I'll share that on Slack in a moment, but if I find it quickly on GitHub, uh virtual view because we do have that in our uh code which is on github entirely and maybe that would help Um yeah, I've had I guess get it. Copy permalink, uh so where is the chat here? I think I send the link on Slack because I cannot find

36:49

Speaker 2: Well no Laura I I can thank you later uh just say

36:53

Speaker 1: I kept it. Um

36:57

Speaker 3: The chat the chat link is there in the left corner. Yeah, yeah.

37:01

Speaker 1: So here is the link. Uh you can take a look at what we are doing in our project So this is basically our own version of GraphQL view. It's like extended version of what the default one does. And over there we have the for example of uh error handling Um we have some additional features like for example for monitoring our API we also have we are using open tracing. uh which is a nice protocol for monitoring uh your apps and uh we do have those open tracing tags over there so whenever a GraphQL requests is starting, we can uh mark where it starts and when it ends, so then we can measure performance of that query, for example. So you can uh look at those examples, uh

37:48

Speaker 1: what we've implemented there for Okay, said it's uh it could be a customized version of of graphene.

37:55

Speaker 2: Cool.

38:04

Speaker 1: Any other questions?

38:06

Speaker 4: Oh yeah, probably uh probably I'll start. Um so hey Marcin, uh can you hear me?

38:12

Speaker 1: Yes, yes.

38:13

Speaker 4: Um cool. Yeah, so first of all, thank you for the for the uh amazing speech. Uh it was uh really nice nice to hear about graphical implementations So yeah, um we've been following uh your Sailor implementation of GraphQL for maybe over a year since we're using data corner case technologies for almost a year already. But pro yeah, we also had a lot of cons and pros uh when compared to to the rest framework. But probably what was always a question for me from this uh from the SALOR implementation Um, do you have any plans on maybe providing your custom implementations, abstractions, file uploaders, and so on, which um uh maybe on uh on the development phase might uh require a lot of time to find the a proper solution, but maybe

39:01

Speaker 4: had Did you have any plans on providing that as a as a library, you know, as a maybe some some implementation which, for example, would be used by your project, but also available for public access and public implementations?

39:14

Speaker 1: Yes, we had some discussions about that. Unfortunately, because the team behind Sailor is not that big. In fact, we are just a bunch of developers and we are we are always so busy with developing stuff at Sailor that Maybe we had no time to actually provide a pull request to Graphene, but probably that would be the best idea. You know, at some point uh I was a bit skeptical about about graphene because Uh this project uh was maintained by one person at some point and then this person like stopped maintaining it. and there was huge discussion whether it will be maintained anymore. And now there are there is a group of people. And I remember that uh there was this transition uh between those maintainers

40:00

Speaker 1: and at that time uh we had many questions about graphene. We were opening some issues on GitHub and they were like sometimes without any response. And I saw also that some pull requests were uh you know they were they were not merging many pull requests from from the community so you know it it like I felt that it's it's not really well maintained at that point And now maybe when the graphene uh version 3 uh comes out, um maybe it would be easier then. Uh so definitely that would be useful for the community. uh because graphene is still the most popular uh graphic framework for pa for python. So for example we could abst abstract away our model mutation implementation so we have our

40:46

Speaker 1: our own abstraction to build mutations from models and it's you know it's also very customized for our in for our needs and it would probably require some time to make it you know more universal But yeah, I I I need to think about that and write that down because it's it's nice that you are saying that you're uh looking at Sailor as an example. Because when we started building uh our API there were I couldn't find any examples of uh GraphQL API in graphic that would be let's say production ready uh only what I could found find was some you know sample projects. So yeah maybe that would be a nice uh nice inspiration for me to actually start thinking about uh abstracting some things away.

41:31

Speaker 1: Because we are gonna use Graphene probably for for some time. We are not thinking about migrating to something else. Although the Ariadne library that I presented

Questions this talk answers

What is GraphQL, and how is it different from REST?

GraphQL lets the client request exactly the data it needs, combine related resources in one request, and use a single endpoint. It supports queries, mutations, and real-time subscriptions, with strong typing and schema-driven tooling.

Discussed at 2:23

How do you structure a GraphQL-first Django project?

A typical project keeps Django’s standard configuration alongside app-level files for GraphQL types, mutations, data loaders, and schemas. Each app exports its schema, and a root schema combines the app schemas and exposes them through the GraphQL view.

Discussed at 9:23

How do I expose a Django model as a GraphQL type with Graphene?

Create a class inheriting from Graphene-Django’s `DjangoObjectType`, associate it with the Django model, and explicitly list the fields to expose. Custom fields can be declared separately and populated with resolver methods.

Discussed at 12:28

How do I define GraphQL queries and mutations in Django?

Queries are declared as fields on a schema class with resolver methods that use the Django ORM; arguments can support filtering, sorting, or pagination. Mutations are classes that define their input, output, validation, and a `mutate` method that changes data and returns the result or errors.

Discussed at 14:01

How do I add JWT authentication and permissions to Graphene-Django?

Use the `django-graphql-jwt` library to provide token and refresh-token mutations, then send the access token in the authorization header for subsequent requests. Its permission decorator can restrict individual resolvers using Django’s permission framework.

Discussed at 19:24

How do I fix the N+1 query problem in GraphQL-Django?

Use data loaders rather than always applying `select_related` or `prefetch_related`. Data loaders collect related-object IDs while resolving a query and fetch them together in a single database query, only when the client requested those relationships.

Discussed at 22:27

How do I test a GraphQL API with Pytest?

Define the GraphQL query or mutation as a Python string, provide its variables, and send it through a GraphQL-capable test client. Then assert that the returned data matches the expected result.

Discussed at 26:18

Can Graphene-Django handle GraphQL subscriptions?

Not out of the box, because Graphene-Django does not provide the ASGI/WebSocket handling needed for subscriptions. Subscriptions are possible with third-party libraries built on Django Channels, although the speaker describes that support as relatively experimental.

Discussed at 27:52

Is Django a good choice for building a GraphQL server?

The speaker considers Django a strong choice because its ORM, migrations, utilities, and declarative patterns make development fast, and adding GraphQL to an existing Django app is relatively easy. The drawbacks are a fragmented ecosystem of additional libraries, limited documentation and learning resources, and an uncertain Graphene roadmap.

Discussed at 28:37

What is the difference between Graphene and Ariadne for Django GraphQL APIs?

Graphene uses a code-first approach and can map Django models to GraphQL types, while Ariadne uses schema-first development and requires more of those mappings to be written manually. Ariadne offers stronger asynchronous and subscription support, including Django WSGI and ASGI views.

Discussed at 31:21

How can I get more useful Graphene errors and debugging information?

The default Graphene GraphQL view can catch errors without clearly identifying the source file. The speaker’s team replaced it with a customized GraphQL view that improves error handling and adds monitoring features such as OpenTracing, and they shared that implementation as an example.

Discussed at 34:50

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos from DjangoCon Europe