概述
解析器负责为我们模式中的特定字段返回数据。到目前为止,我们一直返回硬编码的播放列表数据,但现在是时候用对 REST API 的调用来替换它了。
在本课中,我们将
- 学习如何访问
context
对象在我们的解析器中 - 使用生成的 Spotify
Client
来对端点进行 REST API 调用 - 将 HTTP 响应类型转换为我们的解析器和模式所期望的类型
解析器参数
一个解析器可以接受以下参数:
self
: 代表类本身。它也代表特定parent
的字段(我们将在本课程的后面部分介绍)。- 对于GraphQL 的参数的值。 GraphQL 的参数用于识别、过滤或转换数据。我们将在本课程的后面部分介绍。
info
. 关于当前操作的信息,例如字段名称、路径等。它还包含context
对象,可用于数据库连接、身份验证信息等,正如我们将在本课中看到的那样,我们的 Spotify 客户端!
在本课中,我们将使用info
参数。
从解析器访问 spotify_client
打开api/query.py
文件并找到featured_playlists
解析器 函数。
为了访问spotify_client
对象在context
中,我们将向解析器 函数添加一个新参数,称为info
,类型为strawberry.Info
。
def featured_playlists(self, info: strawberry.Info) -> list[Playlist]:
当一个解析器有一个类型为strawberry.Info
的参数时,Strawberry 将自动将info
对象传递给解析器。
从info
对象中,我们可以提取spotify_client
并将其分配给一个变量。
spotify_client = info.context["spotify_client"]
发送精选播放列表的请求
现在我们有了客户端,我们可以使用它向 Spotify REST API 发出请求。我们将使用我们生成的客户端中的get_featured_playlists
模块,所以让我们在顶部导入它。
from mock_spotify_rest_api_client.api.playlists import get_featured_playlists
此模块中有一些函数,但我们将专门使用asyncio
函数。也有一个同步版本可用,但我们建议使用异步版本以避免在每次向 Spotify API 发出请求时阻塞服务器。
我们需要更新我们的解析器,使其也成为异步的。
- def featured_playlists(self, info: strawberry.Info) -> list[Playlist]:+ async def featured_playlists(self, info: strawberry.Info) -> list[Playlist]:
现在我们已经准备好获取精选播放列表了!
在featured_playlists
解析器 中,我们将调用get_featured_playlists.asyncio
函数,将spotify_client
传递到client
中的参数。
我们将await
该调用并将结果存储在一个名为data
的变量中。
data = await get_featured_playlists.asyncio(client=spotify_client)
返回正确的数据类型
将鼠标悬停在data
变量上,我们可以看到它的类型为SpotifyObjectFeaturedPlaylists
。这是我们之前看到的(在 REST API 文档中)的具有顶层属性message
和playlists
的响应类型。它不是此解析器 函数应该返回的内容;我们希望返回一个Playlist
类型列表。
要获得我们实际需要的数据,我们必须深入到data.playlist.items
中。
items = data.playlists.items
现在将鼠标悬停在items
上,我们可以看到它是一个SpotifyObjectPlaylistSimplified
类型列表。它不完全是一个Playlist
类型,但它确实包含我们需要将它转换为Playlist
类型的属性!
让我们生成一个列表,遍历items
列表中的每个playlist
并根据我们需要的字段(id
、name
和description
)创建Playlist
实例。
playlists = [Playlist(id=strawberry.ID(playlist.id),name=playlist.name,description=playlist.description,)for playlist in items]
最后,我们可以返回playlists
变量。
return playlists
完美!可以将所有内容整合到一个简洁的语句中(无需额外的 变量)。
return [Playlist(id=strawberry.ID(playlist.id),name=playlist.name,description=playlist.description,)for playlist in data.playlists.items]
现在我们可以移除之前硬编码的 Playlist
对象了。
- return [- Playlist(id="1", name="GraphQL Groovin'", description=None),- Playlist(id="2", name="Graph Explorer Jams", description=None),- Playlist(id="3", name="Interpretive GraphQL Dance", description=None),- ]
探索时间!
激动地想知道这些代码都做了什么吗?确保所有文件都已保存,并且服务器正在运行最新更改。
让我们跳到沙盒浏览器 并运行相同的 查询 获取特色播放列表。
query FeaturedPlaylists {featuredPlaylists {idnamedescription}}
看!我们从 REST API 数据源获得了特色播放列表 ✨
与 REST 方法比较
让我们戴上产品应用程序开发者的帽子,思考一下如果我们使用 REST 而不是 GraphQL,这个功能会是什么样。
如果我们使用 REST,应用程序逻辑将包括
- 对
/browse/featured-playlists
端点进行 HTTPGET
调用 - 深入响应 JSON 的
playlists.items
属性 - 仅检索
id
、name
和description
属性,丢弃 所有其他 响应。
还有很多未使用的响应内容!如果客户端应用程序网络速度慢或数据量不多,这种大型响应会带来成本。
使用 GraphQL,我们拥有简洁、干净、可读的 操作,它来自客户端,并以他们指定的精确形状返回,不多不少!
在 GraphQL 服务器 端完成所有提取数据和过滤所需 字段 的逻辑。
注意:正如您所见,REST 和 GraphQL 可以协同工作!您可以通过观看此视频了解更多信息 "GraphQL 和 REST:真正的 BFF - Dan Boerner / API 世界".
关键要点
- Resolver 函数可以接受参数,例如 GraphQL 参数 和
info
。 - 通过使用 GraphQL API 而不是 REST API,我们可以避免处理大型响应数据。
接下来
令人兴奋的进展!在下一课中,我们将学习 GraphQL 参数 以及如何在 resolver 函数中访问它们。
分享您关于本课的问题和评论
本课程目前处于
您需要一个 GitHub 帐户才能在下面发布。还没有? 请改在我们的 Odyssey 论坛中发布。