为 graphql-core 的 Relay 库
项目描述
为 GraphQL Python 的 Relay 库
GraphQL-relay-py 是 Relay 的库,用于 GraphQL-core。
它允许使用 GraphQL-core 轻松创建符合 Relay 规范的服务器。
GraphQL-Relay-Py 是 graphql-relay-js 的 Python 版本,而 GraphQL-Core 是 GraphQL.js 的 Python 版本,GraphQL.js 是 JavaScript 的参考实现,也是 GraphQL 的 JavaScript 实现。
自版本3开始,GraphQL-Relay-Py和GraphQL-Core只支持Python 3.6及以上版本。对于较旧的Python版本,您可以使用这些库的版本2。
入门
为了为这个库提供上下文,需要了解GraphQL以及GraphQL Python实现的基本知识。
关于GraphQL的一般概述可以在README中找到,这是GraphQL规范。
这个库旨在与GraphQL-Core Python参考实现一起工作,这是一个GraphQL服务器的实现。
关于符合Relay规范的GraphQL服务器应提供的功能概述,可以在GraphQL Relay规范上找到,该规范位于Relay网站。该概述描述了作为测试存在于该存储库中的简单示例集。以这种方式开始使用该存储库的好方法是与相应的测试一起浏览该文档和库中的测试。
使用GraphQL Python(graphql-core)的Relay库
安装GraphQL Python的Relay库
pip install graphql-core
pip install graphql-relay
当为GraphQL构建模式时,可以使用提供的库函数简化Relay模式的创建。
以下各节中解释的所有函数都必须从graphql_relay
包的顶级导入,如下所示
from graphql_relay import connection_definitions
连接
提供了用于构建GraphQL类型以及实现返回这些类型的字段resolve
方法的辅助函数。
connection_args
返回字段应提供用于支持双向分页的连接类型的参数。forward_connection_args
返回字段应提供用于支持正向分页的连接类型的参数。backward_connection_args
返回字段应提供用于支持反向分页的连接类型的参数。connection_definitions
返回一个connection_type
及其关联的edgeType
,给定一个名称和一个节点类型。connection_from_array
是一个辅助方法,它接受一个数组和来自connection_args
的参数,执行分页和过滤,然后返回一个符合connection_type
的resolve
函数所期望的对象。cursor_for_object_in_connection
是一个辅助方法,它接受一个数组和成员对象,并返回用于突变负载的游标。offset_to_cursor
接受数组中成员对象的索引并返回用于突变负载的不透明游标。cursor_to_offset
接受一个不透明游标(通过offset_to_cursor
创建)并返回相应的数组索引。
这些方法从测试模式中的示例用法
ship_edge, ship_connection = connection_definitions(ship_type, "Ship")
faction_type = GraphQLObjectType(
name="Faction",
description="A faction in the Star Wars saga",
fields=lambda: {
"id": global_id_field("Faction"),
"name": GraphQLField(GraphQLString, description="The name of the faction."),
"ships": GraphQLField(
ship_connection,
description="The ships used by the faction.",
args=connection_args,
resolve=lambda faction, _info, **args: connection_from_array(
[get_ship(ship) for ship in faction.ships], args
),
),
},
interfaces=[node_interface],
)
这显示了向Faction
对象添加一个连接字段ships
。它使用connection_definitions(ship_type, "Ship")
创建连接类型,将connection_args
作为此函数的参数,然后通过传递船只数组和参数给connection_from_array
来实现解析函数。
对象标识
提供了用于构建节点GraphQL类型和实现围绕本地ID的全球ID的辅助函数。
node_definitions
返回对象可以实现的对象接口,并返回要在查询类型中包含的node
根字段。为了实现这一点,它需要一个将ID解析为对象的函数,以及确定给定对象类型的函数。to_global_id
接受一个类型名称和特定于该类型名称的ID,并返回一个在所有类型中都是唯一的“全球ID”。from_global_id
接受由to_global_id
创建的“全球ID”,并返回用于创建它的类型名称和ID。global_id_field
用于在节点上创建id
字段的配置。plural_identifying_root_field
创建一个可以接受非ID标识符列表(如用户名)的字段,并将其映射到相应的对象。
这些方法从测试模式中的示例用法
def get_node(global_id, _info):
type_, id_ = from_global_id(global_id)
if type_ == "Faction":
return get_faction(id_)
if type_ == "Ship":
return get_ship(id_)
return None # pragma: no cover
def get_node_type(obj, _info, _type):
if isinstance(obj, Faction):
return faction_type.name
return ship_type.name
node_interface, node_field = node_definitions(get_node, get_node_type)[:2]
faction_type = GraphQLObjectType(
name="Faction",
description="A faction in the Star Wars saga",
fields=lambda: {
"id": global_id_field("Faction"),
"name": GraphQLField(GraphQLString, description="The name of the faction."),
"ships": GraphQLField(
ship_connection,
description="The ships used by the faction.",
args=connection_args,
resolve=lambda faction, _info, **args: connection_from_array(
[get_ship(ship) for ship in faction.ships], args
),
),
},
interfaces=[node_interface],
)
query_type = GraphQLObjectType(
name="Query",
fields=lambda: {
"rebels": GraphQLField(faction_type, resolve=lambda _obj, _info: get_rebels()),
"empire": GraphQLField(faction_type, resolve=lambda _obj, _info: get_empire()),
"node": node_field,
},
)
这使用 node_definitions
来构建 Node
接口和 node
字段;它使用 from_global_id
在函数实现中将ID映射到对象的路径中解析ID。然后它使用 global_id_field
方法在 Faction
上创建 id
字段,这也确保了实现了 node_interface
。最后,它将 node
字段添加到查询类型,使用 node_definitions
返回的 node_field
。
突变
提供了一个辅助函数,用于构建具有单个输入和客户端突变ID的突变。
mutation_with_client_mutation_id
接收一个名称、输入字段、输出字段以及一个突变方法,该方法将输入字段映射到输出字段,并在过程中执行突变。然后它创建并返回一个字段配置,该配置可以用作突变类型的顶层字段。
这些方法从测试模式中的示例用法
class IntroduceShipMutation:
def __init__(self, shipId, factionId, clientMutationId=None):
self.shipId = shipId
self.factionId = factionId
self.clientMutationId = clientMutationId
def mutate_and_get_payload(_info, shipName, factionId, **_input):
new_ship = create_ship(shipName, factionId)
return IntroduceShipMutation(shipId=new_ship.id, factionId=factionId)
ship_mutation = mutation_with_client_mutation_id(
"IntroduceShip",
input_fields={
"shipName": GraphQLInputField(GraphQLNonNull(GraphQLString)),
"factionId": GraphQLInputField(GraphQLNonNull(GraphQLID)),
},
output_fields={
"ship": GraphQLField(
ship_type, resolve=lambda payload, _info: get_ship(payload.shipId)
),
"faction": GraphQLField(
faction_type, resolve=lambda payload, _info: get_faction(payload.factionId)
),
},
mutate_and_get_payload=mutate_and_get_payload,
)
mutation_type = GraphQLObjectType(
"Mutation", fields=lambda: {"introduceShip": ship_mutation}
)
此代码创建了一个名为 IntroduceShip
的突变,它接收一个派系ID和一个船名作为输入。它输出相关的 Faction
和 Ship
。然后 mutate_and_get_payload
通过将每个输入字段作为关键字参数获取,构建新的船,执行突变,然后返回一个由输出字段解析的对象。
我们的突变类型然后使用 mutation_with_client_mutation_id
的返回值创建 introduceShip
字段。
贡献
从GitHub克隆此存储库后,我们建议使用 Poetry 创建测试环境。安装 poetry 后,可以使用以下命令进行操作
poetry install
然后您可以使用以下方式运行完整的测试套件
poetry run pytest
要运行部分测试并增加冗长性,您可以添加 pytest 选项,如下所示
poetry run pytest tests/node -vv
要使用 flake8 检查代码风格,请使用以下
poetry run flake8
使用 tox
命令以不同的 Python 版本运行测试套件并执行所有其他源代码检查。您还可以将 tox 限制为单个环境,如下所示
poetry run tox -e py39
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪一个,请了解更多关于 安装包 的信息。