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
descriptionargument
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
descriptionargument on bothstrawberry.fieldandstrawberry.typeis 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.IDtype 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.