11. GraphQL arguments
5m

Overview

Onwards with our next feature!

In this lesson, we will:

  • Learn about and how to access them in a function
  • Learn how to use in an

The mockup

Here's our next feature: the playlist page.

Mockup of the playlist page

We'll most likely get to this page through a few ways: clicking on a specific playlist from the featured playlists page or maybe directly through a URL link.

However we get to this page, we'll need the playlist ID, which makes it a perfect use case for a .

GraphQL arguments

An is a value you provide for a particular in your .

can use a 's provided to help determine how to populate the data for that field. Arguments can help retrieve specific objects, filter through a set of objects, or even transform the field's returned value. For example, a that performs a search usually provides the user's search term as an argument.

A new entry point

Our schema evolves again! We're adding a new entry point.

Inside the Query class, we'll add a new called playlist, which returns a nullable Playlist type. We're making this nullable because it's possible that the playlist we're looking for doesn't exist (for example, it may have been deleted).

This will be async and we'll apply the strawberry.field as a decorator.

api/query.py
@strawberry.field
async def playlist(self) -> Playlist | None:
...

Remember, adding self as an inside the function is good practice.

We'll also add another parameter: id of type strawberry.ID to denote that this should be of type ID in .

Note that the id parameter can be named anything, like playlist_id for example! We recommend collaborating with your team to decide on naming conventions. Using id as the name is a common convention.

api/query.py
@strawberry.field
async def playlist(
self,
id: strawberry.ID
) -> Playlist | None:
...

We'll also include the info parameter, which we'll use later on to access spotify_client:

api/query.py
@strawberry.field
async def playlist(
self,
id: strawberry.ID,
info: strawberry.Info
) -> Playlist | None:
...

At the top of the file, let's import the function to fetch a playlist from the mock_spotify_rest_api_client package, called get_playlist.

api/query.py
from mock_spotify_rest_api_client.api.playlists import get_playlist

Now jumping back to the playlist , let's use this function to fetch the playlist data from the REST API. We'll pass in the same spotify_client value, as well as the id for the playlist_id parameter the function is expecting.

Similar to the featured_playlists , we'll await the results and store them in a data .

api/query.py
spotify_client = info.context["spotify_client"]
data = await get_playlist.asyncio(client=spotify_client, playlist_id=id)

If data is None, this most likely means there wasn't a playlist with that particular ID. We'll return None in this case.

api/query.py
if data is None:
return None

This needs to return a Playlist type, but data (if it isn't None) is a SpotifyObjectPlaylist type.

So let's create a new Playlist object with the data properties we do have have, and return it.

api/query.py
return Playlist(
id=strawberry.ID(data.id),
name=data.name,
description=data.description,
)

Don't forget the description for the ! We can add that to the @strawberry.field decorator,

api/query.py
@strawberry.field(description="Retrieves a specific playlist.")

Let's save our changes and make sure our server is still running successfully with no problems.

Explorer time!

Time to see how our has evolved with those changes! Let's jump back to Sandbox and create a new workspace.

In the Explorer page, navigating back to the root Query type in the Documentation panel, we can see a new : the playlist(...) .

Click on the + button beside "" to add all three playlist fields to the .

http://localhost:8000

GetPlaylist operation in Sandbox

query Playlist($playlistId: ID!) {
playlist(id: $playlistId) {
id
name
description
}
}

We'll notice something new here: a dollar sign ($) followed by the name playlistId.

Variables

The $ symbol indicates a variable in . The name after the $ symbol is the name of our , which we can use throughout the . After the colon is the variable's type, which must match the type of the we'll use it for.

are great—they let us pass values dynamically from the client-side so we don't have to hardcode values into our . We'll use them every time we create a query with arguments.

In our case, we have a called playlistId that the Explorer set up for us down in the Variables section. Right now, it's set to null.

http://localhost:8000

GetPlaylist operation with null variable

If we try to run the now, we'll still get a JSON object back, but this time with an errors key, instead of data:

Response
{
"errors": [
{
"message": "Variable `playlistId` is required.",
"locations": [
{
"line": 1,
"column": 16
}
],
"extensions": {
"code": "HC0018",
"variable": "playlistId"
}
}
]
}

This lets us know that we can't leave the playlistId as null, because the schema specifically defines the id (where we're using the playlistId ) as a non-nullable type!

Let's go ahead and update the null value to a playlist ID we know exists from the featuredPlaylists .

Variables
{
"playlistId": "6Fl8d6KF0O4V5kFdbzalfW"
}

Lastly, we'll rename the to be a bit more descriptive — like GetPlaylistDetails.

GraphQL operation
query GetPlaylistDetails($playlistId: ID!) {
playlist(id: $playlistId) {
id
name
description
}
}

Run the to get the details of the Sweet Beats & Eats playlist!

http://localhost:8000

GetPlaylist operation with playlistId

Practice

What is the purpose of GraphQL arguments in resolvers?
Why is the Playlist type returned from the playlist resolver marked as nullable?
In GraphQL, how is a variable represented in a query?

Key takeaways

  • are values provided for a particular in a . use field arguments to determine how to populate data for that field.
  • The $ symbol indicates a in . The name after the $ symbol is the name of our , which we can use throughout the . After the colon is the variable's type, which must match the type of the we'll use it for.

Up next

We hear you, you're ready for some jams! We'll add the playlist's tracks in the next lesson.

Previous

Share your questions and comments about this lesson

This course is currently in

beta
. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.