Building high-performance, type-safe GraphQL APIs with Strawberry and Django
Published July 10, 2024
This video features Thiago Bellini Ribeiro at DjangoCon US 2023 in Durham, North Carolina, USA.
GraphQL has gained popularity for its ability to offer more flexibility and performance over traditional REST APIs. Strawberry is a new and fast-growing GraphQL library for Python, inspired by dataclasses functionality, that offers a modern and intuitive API for building GraphQL APIs using type hints.
In this talk, we will explore the basics of building a GraphQL API with Strawberry and how it can be integrated with Django in a performant and type-safe way, by generating its types and resolvers directly from Django models. We will also compare and contrast the benefits and drawbacks of GraphQL versus REST APIs, including how GraphQL can help improve frontend development workflows.
Attendees will come away with an understanding of how Strawberry can help simplify the process of building and maintaining GraphQL APIs, and how to use its powerful features to optimize for performance, safety, and flexibility, while also covering its drawbacks and how to avoid some common issues.
This talk was presented at: https://2023.djangocon.us/talks/building-high-performance-type-safe-graphql-apis-with-strawberry-and-django/
LINKS:
Follow Thiago Bellini Ribeiro 👇
On Twitter: https://twitter.com/_bellini666
Website: https://bellini.dev
Follow DjangCon US 👇
https://fosstodon.org/@djangocon
https://twitter.com/djangocon
Follow DEFNA 👇
https://www.defna.org/
Video production by the presenter and DjangoCon US 2023 volunteers.
GraphQL lets clients request exactly the fields and relationships they need from a typed schema, avoiding many REST overfetching and underfetching problems. Strawberry maps Python type annotations and dataclasses to GraphQL types, while Strawberry Django maps those types to Django models and can generate resolvers, filters, lookups, ordering, pagination, permissions, mutations, and async-compatible views. The speaker emphasizes designing APIs as graphs, protecting fields, and avoiding duplicated types, while warning about GraphQL’s N+1 query problem. Strawberry Django’s optimizer addresses this by inspecting the selection set and applying Django ORM techniques such as `only`, `select_related`, and `prefetch_related`, with hints available for computed fields.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Hello everyone, uh thank you for ever for joining. Let's talk. So I'll be talking to you about building high performance type safe GraphQL APIs with Strawberry and Django. And first of all, I am uh I have 35 years old, I am from Brazil. You will notice uh Brazilian accent in my in my speech from time to time. Um I've been developing Python solutions for at least 13 years now, working mostly with uh GraphQL uh solutions together with Django for the past five years. I am also uh a core developer uh from of the the Strawberry GraphQL
API and also the official maintainer of the Strawberry Django integration. Uh so let's start. Um first of all, what is GraphQL? Uh GraphQL is basically a query language for APIs uh to fulfill runtime uh for Uh fulfilling those queries with your exceeding existing data. Uh it basically provides a way for you to Uh define how what your uh API looks like and it gives clients the power to ask exactly for what they want. Here is a meme in the graphical community. So a burger comparison, I think it's a very nice comparison to compare it
to other approaches like REST. So for example, in this if you have a REST API which retrieves a cheeseburger, you can ask uh like uh I want a cheeseburger and you get everything in there with GraphQL. Um you can define a um a query to get the cheeseburger and you can uh the client can ask whatever he wants to to retrieve. So in this case he's asking to retrieve the bun, the lettuce, the paddy, the uh and also the the bun is here two times. I I got this image from from this place I didn't know notice that. But uh and the cheese, but it's keeping the cheese if it is vegan and also the party can be vegan or not.
And you will see that uh If he wanted, he could also ask for the tomatoes, the onions, uh, or not or not even include the lettuce for some reason. So uh this is a nice way to represent the The difference between REST and GraphQL. So the main pros when using GraphQL and why I am using that so much So you uh REST APIs you you'll know that you have uh and uh you sometimes have issues with uh underfetching or overfetching. Um sometimes you will just need uh one or two informations from a resource. And you get all or nothing. And uh if you want more, you want to
you need to make even more requests. So um with uh GraphQL you don't uh you don't have that Graphical forces you to define the type of everything. So the API is very type-safe and it also provides uh an automatic documentation for it. Uh no edge point redundas because uh you you can expose and uh um the c because the client can choose what he wants to consume, you don't need all This is a uh an endpoint for a full cheeseburger, and this is uh for a half cheeseburger. Um so using the the the comparison from before. Um Easy access to relations
because uh you your data will form like your schema will be a graph. So uh if you have uh like oh I have users and the users have friends, so the friends are a relation uh to some other users and he is part of a group which is another relation. And um you can basically retrieve everything without without having to uh make uh a lot of queries to to do that. Uh and no API versioning required. Uh you can basically deprecate anything. You can deprecate types, you can re deprecate attributes. And it will also be automatically documentated on your schema.
There is a steep learning curve Uh rest is very straightforward. Uh you just use you use get, you use post , you use button uh in in in in in MPI and you know what you are expecting from it, but uh GraphQL you need to understand a bit more about how to write uh GraphQL queries and Um it's not very difficult, but there is a uh steep curve in that. Uh caching is more complicated, you you can't just cache get requests Uh there are potential security concerns um if you don't uh map your relations correctly. And potential performance issues if your relations are not
uh handled properly. But Don't fear those cones, strawberry is here for you, as you will see in the in my next slide about strawberry. So how does strawberry work Um I will be exp give a brief explaining about how Strawberry does things and then how uh Strawberry the Strawberry Django integration Django integration does So in here we have an example. I use it uh this event uh as an example. Oh my god. I I misclick it here. I'm sorry about that. So I wanted to use this. So in here, you see that I defined uh uh the the type event
I type user and a talk. So those are types and inside them there are attributes So the name is a string. Uh the exclamation point here marks that it it is mandatory. So if you ask for the name, the name it will be a string, maybe a blank string, but uh string uh it it can't be known uh the user and also the relations you'll see that there are here so the talk has a speaker, which is a user, and also attendees, which is a list of users. And When you are defining your schema, you define your types and you can define how you will
uh in in it um uh talk to your types So you define queries and mutations. Queries are similar to get requests and mutations are similar to post put delete mutations but uh like you define what they will do. In this case for example we have um a talks query which will retrieve a list of talks Uh talk query which will retrieve uh a talk given a slug. Uh speaker uh which given a username will retrieve a user and notice that those two Um don't doesn't have an exclamation point, so if you give it a um uh how can I say this uh non-existing username or a no non-existing user, it should probably return no.
Also uh mute uh mutation for register talk. So in uh for example, I could use this to register a new talk. and attend talk to say, oh I want to attend this talk and so on. So in here we have a in the schema which and DjangoCon could could be using for example, to provide data to its website and allow a backoff system to register new talks and uh you guys to uh register that we'll be attending a talk. And uh uh I don't know did you understand everything that it it was happening in there But uh what if we can write that in pure Python? It will probably be easier to understand.
So spoiler edge we can with strawberry. So for example, getting the the same schema again. If you are familiar with data classes, we can define the same that is here as data classes. So the event became becomes a data class of event you can the the relations are here as well so the speaker is still a user uh which is defined here and When we want to expose that in Strawberry, we basically exchange the the data class here with uh etch Strawberry duck type. Strawberry is basically a wrapper on top of uh data classes, so strawberry types are basically valid data classes.
And uh For queries and mutations, we can write them as well as Python using Python idiometric ways. For example, for talks, we can we have a strawberry field here, uh a function talks, which will return a liter uh oh Oh yeah, don't it's right. It's correct. I uh I was looking at this one. Uh so here uh I didn't write the code for obvious reasons, but I would Try to return a list of talks in here. The talk the same. I can return here a talk or none. As I mentioned, this one is not mandatory, so uh none can be returned
And mutations, the same. I have a register talk here, which I received the the event, which is probably the the IG, a topic, a headline, a description, which is not mandatory and I'll return the talk after I created it and also the attendee talk. So pretty straightforward. That's I think it's the what I love the most about Strawberry. All of this that I am showing is uh basically everything that you need to do to create a basic uh strawberry application. Uh so and using that as an example, how would I uh query that data after that?
So If uh if I was using uh rest, I would send a get request to uh slash api slash uh talks. In this case, I will always be sending a post. Uh and this is basically the the body of the request. So I am asking uh the talks, I want to retrieve the slug, the data, the topic, and the speaker, he's uh an entity So I need to uh ask for attributes inside it and I want to ask just the name. And an example of the resulting payload would be Something like this. So I have the talks, the name of the the the query that I have here. And inside it
I have uh an array and each object is a talk and it and the strawberry API I'm sorry the GraphQL API ensures that the types here will match the ones that are exposed in my schema. Um another example would be if I want to uh in this one I retrieve the the list of queries. In this one I am retrieving uh a single query. Um in this I am passing the the slug as a variable. I can uh uh define a lot uh and pass a lot of uh as much variables as I want that there is a way that those will be inserted in the in the body But I don't know I don't
don't want to get into details in this talk, but in here you can see that I am returning a single a single result. So the first one would be use it like in the stro in the DjangoCon uh website for example. The first one would be use it to list uh all to all the talks in the schedule, this one would be use it to retrieve like oh I I got I got into the the uh the the talk page. So I have this lug and I want to retrieve its data. So um this is an example. Uh so how can we write general GraphQL APIs using Strawberry? Uh so uh as I as I presented before, um
I I can def define those using the strawberry type decorator and not only I can uh define Define attributes this way, but also I can define some uh uh some attributes which need to be calculated using uh using the strawberry field uh decorator. Just like this I have I want to to expose an age and since I have the birth date I don't need to Uh pass it again. I can just calculate it using the today 's date and it will be exposed in the same way. It will use the the annotations, the type annotations in here. So it will say, oh
The age is and uh will return an integer in in my schema, and that's it. And the same for the query. I have, for example, in this case, I have a user And I can I say that it will return a user, and I return the user and just as data classes, I just I can just instantiate that user. Um so uh the same goes for relations. Uh in this case I have emails, which is a list of emails, and Friends, which is a list of the user itself. So when returning those, I can just uh instantiate the the user. Uh the friends in here are some other users.
Emails is a list of Of emails, and you can see that this the same rule rules that applies to data classes. So for example, is confirmed in this primary, uh default to false. uh this one has a default factor of list so uh if I don't want to I can't I don't need to pass those and so on. So now uh how to integrate those with the the Django ORM? Getting started with that, firstly we want to be able to expose the GraphQL, especially because we want to start playing with it. And uh there's not
nothing uh much that we need to do. We just need to expose a view. Strawberry provides two views, a graphql view and a and a uh async GraphQL view Which we can just expose. Uh GraphQL has a single entry point, so it's not like Restro, I need I have slash API slash user slash API slash orders or something like that. I just have a single one and the card that I am doing will be sent in the in the post body. So I need just need to define my schema. The schema will receive the queries, the mutations in here, just like This this is a query. You can define a lot of queries and then merge those together to pass
there. Not going to also in go into details about that, but you can do that And if by some extensions, this one is high highly recommended. I will talk more about why in the end of this talk And when doing post requests to this, you will be querying data. And when doing get requests to this, as long as the graphic QL uh is enabled and in here and enable enabling it as long as the the the debug is enabled. you will get a screen like this, which is basically a pay playground which in which you can introspect your schema, you can do some run some queries just like the
the Django REST framework as a a way to uh to test there. Um and that's it. So j just wanted to show you how it looks like So uh using uh strawberry together with Django. As I showed you, um it's easy to know um That you can basically define inside those uh we call those uh in graphical call those resolvers. So I have a field here, emails. It's easy to know that I can basically just uh query the Django or m directly in here and instantiate those uh those types directly using using the data.
So for example Uh let's get the user in here. I am retrieving a user, giving his uh primary key, and then instantiation the the the user type in here. But of course that's not uh Like you are doing a lot of how can I say this? A lot of work in here, you need to define your your model, you need to define your type, and then you need to map Your model to your type. So there is for sure a better way of doing this, which is using the strawberry Django integration. In this case Uh you will notice that uh the the decorator is very similar to
the to the one that Strawberry uses. Uh you use strawberry Django. type, but you pass the the model to it Um so uh the integration will know that this type relates to uh to this model and We'll do some mapping for you. Uh in this case, we are still typing and it's you can always do that, so I am still saying that the email has a string. A is a string, the is conformity is a boolean. The the user is a user type Uh so as I was saying, what is happening here? We are using strawberry Django uh. type to define the user. Emails is a list of of email type, user is a strawberry field.
Um Yeah, and this is important to talk about. And the query itself, you'll notice that I didn't define a function, a resolver to it And the integration will do that for us. So when I say that I have a user which will return a user type and I assign it to a strawberry Django dot field It will automatically create a resolver for me which will receive a single uh single argument called PK. Which is the primary key and retrieve the user for me. And the same up the same goes for users here, uh, which uh is is typed to return a list of user type And this one will
create a resolver which will basically query uh user. object. all and return it. Of course, this is the the easiest way of doing this. I can always uh define my own and I will show some examples of how to add some custom filters and ordering to it Imagination as well. But we can do better. We can actually just use uh the strawberry. auto Annotation in here. So for example, the same as before. I have the email type in here. But instead of typing everything I uh I I already have that uh
typed on my ORM. I know that uh the email is using a sharp field, so I know that I should expose that as a string and so on. So another thing. that strawberry the strawberry Django integration will do is to automatically convert uh use will introspect the the model. and um change at r in runtime all the typings in here to uh should they're correct Representation. So uh sharp field will become a string, uh sharp field which can be null will become a string or none, and so on. And also uh notice about this, uh I will talk about this um uh a little later.
But uh I have a name in here which I am returning the like uh concat concatenation concatenating the the first name and the last name here and I I I added uh an only first name and last name for optimization reasons. I will I will explain you will understand why I did this uh soon. So what else the the let me just see okay so what else the the strawberry Django integration can do to facilitate your coding? Uh so the strawberry type acts acts as a protocol to the model as I mentioned. So you can just uh uh decorate the type with uh strawberry Django.
type user and When you say that you can return a user type, you can just return the model itself. Otherwise like If if you try when using strawberry directly and you have like a user type and you try to return something else, uh the graph GraphQL will not allow you. Basically, GraphQL Dictates that the servers needs to ensure that the data being returned is actually the data that it is defined in the schema. So if you say that you return a string and you try to return a boolean or an integer, uh the server itself should not allow you to do that. The same goes
Here, so if you say that you are you returning a user type, you should be returning a user type. But in this case, because the user type is another is decorated with the strawberry Django dot type user uh you are saying that you can actually return a user and it will know how to resolve it It has automatic resol uh resolver generation as I'm uh as I mentioned as well. So for example, in this case I have a user type and an email type. The email type, for example, has an email and annotated with strawberry. auto. When trying to resolve it, and this is how actually uh Strawberry works, it will retrieve the the uh
the email in here, for example, using get attribute in the object. So as long as The the object that I am returning for that it for that email type which is an email from the ORM has the email it will work, meaning that I can also expose properties this way, uh and so on. And also, as I said before, uh fields inside the quer uh the root query will also uh generate uh resolvers. To return either single results or a list of results, like in this case. This is inside the user type, but it it
goes, it does the same Uh it uh strawberry junk provides you ways to filter uh list results. So when I say uh when I say that They're querying here and returning a list of users. This should be users, I'm sorry about that. But this this is returning a list of users and this is returning a list of emails. I can define filters, which is uh the the way to define those is very similar to the way of defining types. In in here I am using strawberry Django. filter, which is uh behind the scenes an input, which is uh similar to types in GraphQL, but uh inputs you can use to
pass to as arguments. uh to uh to queries and uh i am what i am doing here is to say that the email filter can be filtered by is confirmed Or uh the the user filter itself. So filters can be nisted. And the user filter can be few can be filtered by uh the primary key. Uh in the in this case, uh the email type I am passing the filters to the decorator itself, meaning that everywhere where the email type is defined to return as a list. Uh this filter will be inserted or in for
for the user I am passing it directly to the field. So I don't want all lists of users to ins to get injected, to have to get the the filter injected. So I can choose where I want. And it will what we it will do will be to generate uh an schema like this. So uh This is this uh what is defined here will in the end generate a GraphQL schema similar to this. So the the the The email filter and uh this should look like actually this is uh incorrect this is uh read and as type it should be an input. I'm sorry about that. The same goes for the user filter here
But I have the email filter, the the email type, the user filter, the user type, and when querying the users You will see that I can receive an argument, an optional argument here called user filter and the emails, the email filter as well Uh and when uh uh the I will show some examples in the next slide. Uh filters can also uh use lookups So the lookups that we are used to in in Django. Uh and we can just uh we can define everything in here. just by passing lookups equals to true to the filter itself. So for example
in this case When doing this, the email which is uh decorated with strawberry. auto, it will be converted to a lookup filter So I can now instead of asking, oh I want to filter by this specific email, I can ask For emails that contain a given string or starts with a given string, and so on. It looks like this, although uh it's not v uh I know that it's not valid for everything like The range is not valid for strings and boolean the range is not uh of course valid for uh the booleans But it's uh because the way it is uh defined, so it will basically
uh uh create the same lookup for all the types. Be it uh it can be an integer, uh date time, a date, object, and so on. Uh an example, how to use that. So if I want to list an email, all emails that ends in at gmail. com or at yahoo. com, I can pass The filters argumenting here to the emails email is at gmail. com And the same, oh I want to list all emails for the users with the primary key one, two, uh, and three. Oh , thank you. Thank you.
I can just pass uh as I mentioned the the nisted uh the nisted filtering The I can pass the user the p where the PK is in list is in one, two, or three. Um I can I can also ask to uh order the the results Uh it it's very similar to how the filters work, but in this case uh what will get generated Is uh enan, inam uh of ascending or descending And as you can see, uh it will be also be inserted as an argument to the to the list resolver. as well.
Of course I can use filters together with uh ordering. I am just uh showing x uh the examples separately to uh make it easier to explain But uh you will probably want to use those uh together. And as an example, asking uh uh for the emails ordered by the the user's PK in an ascending way and then for is confirmed in a descending way. And also uh I can ask those types or the the the field itself to be uh exposed uh with pagination. In this case, there is no type that will be will get generated.
It's just the uh the off uh an offset and limit parents will be injected inside the the resolver. So um re really uh straightforward way to use that. So for example, if I want to retrieve the 50 page of uh 10 uh results per page per generation list, I can give I can ask it, oh I want the the uh using an offset of 50 and limit it by 10 It also uh provides you a way to protect your fields using the Django permission and permissioning system. So the integration provides some uh set of useful extensions in there.
Um and the the strawberry the strawberry field all strawberry fields, but in this case I'm using still the strawberry Django field. You can pass some extensions which you can also write your own custom extensions, but in this case The Strawberry Django integration provides uh and this is because there used it to be uh a project called Strawberry Django Plus, which which I altered But uh this is all now integrated into strawberry, uh the strawberry uh Django integration. So again, I'm sorry about that But uh you can import this and use this uh it like this. So for example, if I want uh a field, this can only be accessed by someone who is a staff.
I can I will say that users can only be listed by staff users by passing the easy staff extension in here uh only staff users will be able to access it if the user does doesn't have the easy staff uh attribute equals to true then uh an error will be will be erased and after the the users are resolved to resolve uh the attributes in here uh for example to get the birth date I am saying that the user needs to have this permission in the Django uh permission and system to see the birth date and the emails only if the user is a super user and so on.
But as I said you can also define your own custom uh permissionings And I I should have clicked this before. Other features and highlights that it provides. So Strawberry itself and the and the integration is async friendly. Um you can use strawberry strawberry and strawberry django uh either using WSGI or ASGI. I personally personally prefer ASGI. There is a lot more stuff that you can do using ASGI. Uh QG mutations uh just like um it provides some built-in ways to define mutations for creation update uh for
to create update and delete objects Cursor pagination, uh you have the the limit offset approach, but there are ways for you to implement your own cursor pagination using the the relay spec. which I'm not going to get into details in here, but you can see the documentation in there. Acquire optimizer, which I am going to talk. uh right uh very soon now uh about it and the Django the debug to bar integration which uh you saw in my in uh a picture i i i showed before When you run a query, you can see what the query looks like using the the Django to Bar integration.
And also it has integrations with uh Django channels Django channels to use with subscriptions, which is not covered here, but you you have queries, you have mutations, and you have subscriptions, which are is a way for you to get uh data that gets incrementally incrementally uh sent to you. Uh so some come common pitchfalls to pay attention. The first one, there are more than those, but I am going to mention three and focus on the the third one. Not protecting your graph Which is um basically for in in this example, for example, uh if the user is
um um is publicly exposed. Um if I don't pay attention to this, everyone can see uh the the the emails now as long as they know that the emails is there to be queried. Uh a solution to this would be to either use a per the the permission extension that I mentioned before or you can define your own uh your own resolver and like for example in this case I am checking who is the current user and I will raise a permission denied if the user is not The user that I am resolving here is not himself or the user is not a staff. So only staff users or the user himself
can see the emails. everyone else if they try to retrieve this erase a permission denied error. Um another common pitchfall is not thinking thinking in graphs So a lot of people coming from REST. I was one of those people in the past. Uh we'll sometimes try to for example I need to ex to expose the users in uh in in one place And in uh like in the back offs, I want to expose the users with their emails. And they will do something like this. So create two types A type for the user, a type for the user with emails and shoot separated queries. So you don't need to do this You can just expose a single user.
As I said, the client can choose if he wants to consume the emails, if he wants to retrieve the emails or not And if you want to protect it somehow, you can use what I explained it before. Unnecessary types duplication. So, for example, in here, say that I have a sale order and I have a card, both of them will have uh items in it, which uh will be uh represented by a tuple of uh a product and the quantity of that that product and it you you can see that it looks the same in the cart item and in the sale order item.
Instead of duplicating this type, I can have a single type in here, product item. and say that the sale order and the cart uh both have a list of items and uh expose it um using the same type. Uh of course Sometimes I will have extra attributes in here and for this I could use uh interfaces which I am not covering today due to the lack of time but uh Uh think of them as like protocols in the Python uh typing system. And the major one that I that I see is the Not pay paying attention to the N plus one issue. So GraphQL
has an intrinsic N plus one issue. Don't know if you can figure it why figure out why But that happens because uh the client can choose whether uh if he wants to include a field or not. So there is no way for you to know in advance if the the uh the client is going to ask for a given field. So uh I if I am retrieving using this example If I am retrieving uh a list of users, uh I don't know if they are going to ask for the the emails or not. And um if they ask I am going to uh like if I have uh uh a thousand users, the server will have to execute uh a thousand and one
queries, one to retrieve the lister the list of users and another uh thousand true uh for each uh list of users for each user. Um we could change change that to use uh Django's prefect related To always uh pre -fetch the the user's emails, but now if the the client doesn't ask for the list of emails, we are overfetching our database. Which is uh better but it's not uh the best approach. So how to avoid a plus one issues? Because I am running out of time, I'm not going to mention data loaders. Um This is how GraphQL and Strawberry handles, and it's uh
a nice way to handle this. And you 'll probably still want to use something like this for more complex scenarios. But how the strawberry Django integration can help you solve this automatically for you. Strawberry Django, the strawberry jjango integration as long as you enable the the the optimizer uh in extension It will uh introspect the query that you are making and the jango and your model. And when you return a query set to it, it will Uh call uh the the query sites API to
uh optimize that query. So for example, if I have uh the my user has a list of a hundred uh uh uh columns uh it will call dot only to only select what i am asking for so i am only asking for first name last name and Something else. It will only retrieve from the database the first name, the last name, and something else. It will join any relations using select related. So When asking for the email, the email has a user as a foreign key, so which will use select related to avoid those n plus one issues. The same goes for one to many or many too many relations using refetch related.
And you can also give it optional type hints to for it uh so it can know uh how to resolve something which is not Uh type it in the Django or m. And you can also give some type hints for it to use for annotations. For example, Uh in this case, uh if we have this schema and this uh and we are acquiring it like this so we are asking for a list of users getting the the group name which is a foreign key from the from the the user type and the uh and a list of emails and ask asking it to retrieve only the email and if it is the primary email
or not The resulting query set will look something like this. So it will retrieve all the users, uh asking it to retrieve only the the the primary key and the the group 's name uh selecting uh the group select asking it to select related the group and also doing a prefetch related for the emails and asking each uh inside it to to retrieve only the email and if it is primary or not. You can also give it some uh some optimization hints So as I mentioned, uh for example the name I want you to expose it as uh as a uh a string oh and this is is wrong this
this would should be um uh a string equals to strawberry dot field and I am annotating it with uh concat Actually this one is is an example of using uh uh Hints for annotations, uh but you can also do something like this. So the d age that we mentioned before. Um The the the integration has no way to know the that the age requires the birth date. So I am uh giving it a hint that it should load the birth date also when calling the dot only and then I can access this without
And um oh okay, so uh okay, uh I just uh run out of time. But yeah, uh the summary of it is that it um it's this the this the um the usage is very straightforward and actually this was mostly uh the the end of what i wanted to to to talk about And uh here are some resources in case you want to to know more about this. Some some of those are uh strawberry links. And the the remaining ones are more general to graphical itself. And Well I thank you very much about uh for this.
Uh hope you all enjoyed. If you want to to know more, I I will be here. Feel free to read me to for any questions and Yeah, I think that's it. I'll go back to this if you want to take a look at the the care code. So thank you all.
GraphQL lets clients request exactly the fields they need from a typed schema, which helps avoid REST’s overfetching and underfetching. It also provides schema-based documentation, easy access to relations, and usually avoids API versioning through deprecations.
Discussed at 2:42Define your schema as Python data classes decorated with `strawberry.type`, use type annotations for fields and relations, and define queries and mutations as Python functions with Strawberry decorators. Strawberry uses those annotations to expose the corresponding GraphQL types.
Discussed at 8:54Send a POST request to the single GraphQL endpoint with a query in the request body, selecting the fields and nested fields you want. Variables can be supplied for arguments such as a talk’s slug, and the response follows the types defined in the schema.
Discussed at 11:14You can manually map Django models to Strawberry types and write resolvers, or use `strawberry_django.type` with a model so the integration performs much of the mapping automatically. Django model instances can then be returned directly for the corresponding GraphQL types.
Discussed at 18:12Use Strawberry Django filter definitions to expose Django-style filters and lookups, attach them to list fields, and add ordering definitions for ascending or descending results. Pagination can inject offset and limit arguments, while nested filters can follow model relationships.
Discussed at 25:06Attach permission extensions such as the staff-only extension to fields, or write a custom resolver that checks the current user and raises a permission error. The integration can also require specific Django permissions or superuser status for individual fields.
Discussed at 31:17Enable the Strawberry Django optimizer extension. It inspects the GraphQL query and Django models, then uses `only`, `select_related`, and `prefetch_related` to fetch only requested columns and efficiently load foreign-key, one-to-many, and many-to-many relations.
Discussed at 40:34Note: 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.
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 14, 2026