Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A library to help construct a graphql-py server supporting react-relay

License

NotificationsYou must be signed in to change notification settings

graphql-python/graphql-relay-py

Repository files navigation

GraphQL-relay-py is theRelay library forGraphQL-core.

It allows the easy creation of Relay-compliant servers using GraphQL-core.

GraphQL-Relay-Py is a Python port ofgraphql-relay-js,while GraphQL-Core is a Python port ofGraphQL.js,the reference implementation of GraphQL for JavaScript.

Since version 3, GraphQL-Relay-Py and GraphQL-Core support Python 3.6 and above only.For older versions of Python, you can use version 2 of these libraries.

PyPI versionTest StatusLint StatusCode Style

Getting Started

A basic understanding of GraphQL and of the GraphQL Python implementation is neededto provide context for this library.

An overview of GraphQL in general is available in theREADME for theSpecification for GraphQL.

This library is designed to work with thetheGraphQL-CorePython reference implementation of a GraphQL server.

An overview of the functionality that a Relay-compliant GraphQL server should provideis in theGraphQL Relay Specificationon theRelay website.That overview describes a simple set of examples that existastests in this repository.A good way to get started with this repository is to walk through that documentationand the corresponding tests in this library together.

Using Relay Library for GraphQL Python (graphql-core)

Install Relay Library for GraphQL Python

pip install graphql-corepip install graphql-relay

When building a schema forGraphQL,the provided library functions can be used to simplify the creation of Relay patterns.

All the functions that are explained in the following sections must beimported from the top level of thegraphql_relay package, like this:

fromgraphql_relayimportconnection_definitions

Connections

Helper functions are provided for both building the GraphQL typesfor connections and for implementing theresolve method for fieldsreturning those types.

  • connection_args returns the arguments that fields should provide whenthey return a connection type that supports bidirectional pagination.
  • forward_connection_args returns the arguments that fields should provide whenthey return a connection type that only supports forward pagination.
  • backward_connection_args returns the arguments that fields should provide whenthey return a connection type that only supports backward pagination.
  • connection_definitions returns aconnection_type and its associatededgeType, given a name and a node type.
  • connection_from_array is a helper method that takes an array and thearguments fromconnection_args, does pagination and filtering, and returnsan object in the shape expected by aconnection_type'sresolve function.
  • cursor_for_object_in_connection is a helper method that takes an array and amember object, and returns a cursor for use in the mutation payload.
  • offset_to_cursor takes the index of a member object in an arrayand returns an opaque cursor for use in the mutation payload.
  • cursor_to_offset takes an opaque cursor (created withoffset_to_cursor)and returns the corresponding array index.

An example usage of these methods from thetest schema:

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=lambdafaction,_info,**args:connection_from_array(                [get_ship(ship)forshipinfaction.ships],args            ),        ),    },interfaces=[node_interface],)

This shows adding aships field to theFaction object that is a connection.It usesconnection_definitions(ship_type, "Ship") to create the connectiontype, addsconnection_args as arguments on this function, and then implementsthe resolver function by passing the array of ships and the arguments toconnection_from_array.

Object Identification

Helper functions are provided for both building the GraphQL typesfor nodes and for implementing global IDs around local IDs.

  • node_definitions returns theNode interface that objects can implement,and returns thenode root field to include on the query type.To implement this, it takes a function to resolve an ID to an object,and to determine the type of a given object.
  • to_global_id takes a type name and an ID specific to that type name,and returns a "global ID" that is unique among all types.
  • from_global_id takes the "global ID" created byto_global_id, andreturns the type name and ID used to create it.
  • global_id_field creates the configuration for anid field on a node.
  • plural_identifying_root_field creates a field that accepts a list ofnon-ID identifiers (like a username) and maps then to their correspondingobjects.

An example usage of these methods from thetest schema:

defget_node(global_id,_info):type_,id_=from_global_id(global_id)iftype_=="Faction":returnget_faction(id_)iftype_=="Ship":returnget_ship(id_)returnNone# pragma: no coverdefget_node_type(obj,_info,_type):ifisinstance(obj,Faction):returnfaction_type.namereturnship_type.namenode_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=lambdafaction,_info,**args:connection_from_array(                [get_ship(ship)forshipinfaction.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,    },)

This usesnode_definitions to construct theNode interface and thenodefield; it usesfrom_global_id to resolve the IDs passed in the implementationof the function mapping ID to object. It then uses theglobal_id_field method tocreate theid field onFaction, which also ensures implements thenode_interface. Finally, it adds thenode field to the query type, using thenode_field returned bynode_definitions.

Mutations

A helper function is provided for building mutations withsingle inputs and client mutation IDs.

  • mutation_with_client_mutation_id takes a name, input fields, output fields,and a mutation method to map from the input fields to the output fields,performing the mutation along the way. It then creates and returns a fieldconfiguration that can be used as a top-level field on the mutation type.

An example usage of these methods from thetest schema:

classIntroduceShipMutation:def__init__(self,shipId,factionId,clientMutationId=None):self.shipId=shipIdself.factionId=factionIdself.clientMutationId=clientMutationIddefmutate_and_get_payload(_info,shipName,factionId,**_input):new_ship=create_ship(shipName,factionId)returnIntroduceShipMutation(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=lambdapayload,_info:get_ship(payload.shipId)        ),"faction":GraphQLField(faction_type,resolve=lambdapayload,_info:get_faction(payload.factionId)        ),    },mutate_and_get_payload=mutate_and_get_payload,)mutation_type=GraphQLObjectType("Mutation",fields=lambda: {"introduceShip":ship_mutation})

This code creates a mutation namedIntroduceShip, which takes a factionID and a ship name as input. It outputs theFaction and theShip inquestion.mutate_and_get_payload then gets each input field as keywordparameter, performs the mutation by constructing the new ship, then returnsan object that will be resolved by the output fields.

Our mutation type then creates theintroduceShip field using the returnvalue ofmutation_with_client_mutation_id.

Contributing

After cloning this repository from GitHub,we recommend usingPoetryto create a test environment. With poetry installed,you do this with the following command:

poetry install

You can then run the complete test suite like this:

poetry run pytest

In order to run only a part of the tests with increased verbosity,you can add pytest options, like this:

poetry run pytest tests/node -vv

In order to check the code style with flake8, use this:

poetry run flake8

Use thetox command to run the test suite with differentPython versions and perform all additional source code checks.You can also restrict tox to an individual environment, like this:

poetry run tox -e py39

About

A library to help construct a graphql-py server supporting react-relay

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors8

Languages


[8]ページ先頭

©2009-2025 Movatter.jp