Overview
Time to level up from "Hello world" to "Hello playlists"!
In this lesson, we will:
- Examine a mockup design and create a GraphQL schema from it
- Create our first object type
- Learn how to document a GraphQL schema with the
description
argument
The mockup
To kick things off, let's take a look at this page from the MusicMatcher app:
It showcases a grid of featured popular playlists that you may be interested in!
Breaking each playlist down, we can start to see what pieces of data the client app will need. This process of breaking down a mockup to pieces of data is called schema-first design.
A playlist needs a name and a description, which are both pieces of text.
Strawberry uses a code-first approach to implementing a GraphQL server but it's still helpful to keep the schema-first design principles in mind; thinking about what types and fields our resolver functions will be defining based on the mockup designs and data that the app developers expect.
The Playlist
type
Let's start with the Playlist
type. In the types
folder, create a file called playlist.py
.
📦 odyssey-intro-strawberry┣ 📂 api┃ ┣ 📂 types┃ ┃ ┣ 📄 __init__.py┃ ┃ ┗ 📄 playlist.py┃ ┣ 📄 __init__.py┃ ┣ 📄 query.py┃ ┗ 📄 schema.py┣ 📄 // other folders & files
We'll import strawberry
at the top, define the class and apply the @strawberry.type
annotation to it.
import strawberry@strawberry.typeclass Playlist:...# Playlist properties go here
Inside the Playlist
class, we'll start by defining the name of our playlist as a property with type str
.
name: str
By default, this field is non-nullable, so a playlist requires a name.
Next, let's define the playlist's description, which is also a str
type. A description can be null
, so we'll mark it as such using the | None
syntax.
description: str | None
One more thing! Even though it wasn't part of the mockup, it's common practice to also define an identifier for a class. Looking ahead, when we click into a playlist, we'll need to have a way to retrieve the details for that specific playlist, and that's exactly what the identifier (or ID) is for.
IDs in GraphQL are represented as ID
scalar types. Python doesn't have a built-in ID
type, but fortunately, Strawberry provides a strawberry.ID
type that we can use.
id: strawberry.ID
The three properties we've defined for a playlist (id
, name
and description
) act as the resolvers for those fields. Behind the scenes, Strawberry automatically generates resolvers for each field based on the property name. For example, the name
field will have a resolver that returns the value of the name
property.
Exploring the schema
What does this Playlist
class look like in our GraphQL schema now? Let's find out!
We'll first need to register the Playlist
class with our GraphQL schema.
Open up the api/schema.py
file and import the Playlist
class at the top of the file.
from .types.playlist import Playlist
Next, where we defined strawberry.Schema
, we'll add another parameter called types
and assign the Playlist
class in the list it accepts.
schema = strawberry.Schema(query=Query, types=[Playlist])
Save all our changes and restart the server.
Back to Sandbox, let's check out the Schema page. Select Objects on the left-hand side and click Playlist.
Awesome, we've accounted for all the playlist fields!
Right now, the details column shows "No description". Although the field names feel fairly self-explanatory right now, it's good practice to document the types and fields of your schema, especially for consumers of our graph.
Documenting our schema
We use GraphQL descriptions to document a schema. (Not to be confused with our playlist's description field!) In Strawberry we use the description
argument of strawberry.type
, which takes a string
as an argument that describes the type.
Back to our Playlist
class, let's add the description
argument to the @strawberry.type
decorator.
@strawberry.type(description="A curated collection of tracks designed for a specific activity or mood.")class Playlist:...
Next, let's add GraphQL descriptions to the Playlist
fields. We'll need to use the strawberry.field
function for each field, passing in the description
argument.
id: strawberry.ID = strawberry.field(description="The ID for the playlist.")name: str = strawberry.field(description="The name of the playlist.")description: str | None = strawberry.field(description="Describes the playlist, what to expect and entices the user to listen.")
Save our changes and switch over to Sandbox to see our clear and helpful descriptions!
Practice
Key takeaways
- Breaking down a mockup into data pieces and implementing features based on client application needs is known as schema-first design.
- The
description
argument on bothstrawberry.field
andstrawberry.type
is used to add clear and helpful descriptions to GraphQL types and fields. It will be displayed in GraphQL IDEs such as Apollo Sandbox. - The
strawberry.ID
type defines the identifier for the GraphQL type. It indicates that the associated property represents a unique identifier.
Up next
We need a way to query for a playlist. Right now, it's just floating in our schema without a way to access it. Let's make it available through our Query
type — our entry point to the schema!
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.