@@ -63,47 +63,53 @@ from graphql_relay import connection_definitions
6363### Connections
6464
6565Helper functions are provided for both building the GraphQL types
66- for connections and for implementing the ` resolver ` method for fields
66+ for connections and for implementing the ` resolve ` method for fields
6767returning those types.
6868
6969 - ` connection_args ` returns the arguments that fields should provide when
70- they return a connection type.
70+ they return a connection type that supports bidirectional pagination.
71+ - ` forward_connection_args ` returns the arguments that fields should provide when
72+ they return a connection type that only supports forward pagination.
73+ - ` backward_connection_args ` returns the arguments that fields should provide when
74+ they return a connection type that only supports backward pagination.
7175 - ` connection_definitions ` returns a ` connection_type ` and its associated
7276` edgeType ` , given a name and a node type.
7377 - ` connection_from_array ` is a helper method that takes an array and the
7478arguments from ` connection_args ` , does pagination and filtering, and returns
75- an object in the shape expected by a ` connection_type ` 's ` resolver ` function.
79+ an object in the shape expected by a ` connection_type ` 's ` resolve ` function.
7680 - ` cursor_for_object_in_connection ` is a helper method that takes an array and a
7781member object, and returns a cursor for use in the mutation payload.
82+ - ` offset_to_cursor ` takes the index of a member object in an array
83+ and returns an opaque cursor for use in the mutation payload.
84+ - ` cursor_to_offset ` takes an opaque cursor (created with ` offset_to_cursor ` )
85+ and returns the corresponding array index.
7886
7987An example usage of these methods from the [ test schema] ( tests/star_wars_schema.py ) :
8088
8189``` python
82- ship_edge, ship_connection = connection_definitions(' Ship ' , shipType )
90+ ship_edge, ship_connection = connection_definitions(ship_type, " Ship " )
8391
84- factionType = GraphQLObjectType(
85- name = ' Faction' ,
86- description = ' A faction in the Star Wars saga' ,
92+ faction_type = GraphQLObjectType(
93+ name = " Faction" ,
94+ description = " A faction in the Star Wars saga" ,
8795 fields = lambda : {
88- ' id' : global_id_field(' Faction' ),
89- ' name' : GraphQLField(
90- GraphQLString,
91- description = ' The name of the faction.' ,
92- ),
93- ' ships' : GraphQLField(
96+ " id" : global_id_field(" Faction" ),
97+ " name" : GraphQLField(GraphQLString, description = " The name of the faction." ),
98+ " ships" : GraphQLField(
9499 ship_connection,
95- description = ' The ships used by the faction.' ,
100+ description = " The ships used by the faction." ,
96101 args = connection_args,
97102 resolve = lambda faction , _info , ** args : connection_from_array(
98- [getShip(ship) for ship in faction.ships], args),
99- )
103+ [get_ship(ship) for ship in faction.ships], args
104+ ),
105+ ),
100106 },
101- interfaces = [node_interface]
107+ interfaces = [node_interface],
102108)
103109```
104110
105111This shows adding a ` ships ` field to the ` Faction ` object that is a connection.
106- It uses ` connection_definitions('Ship', shipType ) ` to create the connection
112+ It uses ` connection_definitions(ship_type, "Ship" ) ` to create the connection
107113type, adds ` connection_args ` as arguments on this function, and then implements
108114the resolver function by passing the array of ships and the arguments to
109115` connection_from_array ` .
@@ -131,40 +137,49 @@ An example usage of these methods from the [test schema](tests/star_wars_schema.
131137``` python
132138def get_node (global_id , _info ):
133139 type_, id_ = from_global_id(global_id)
134- if type_ == ' Faction' :
135- return getFaction(id_)
136- elif type_ == ' Ship' :
137- return getShip(id_)
138- else :
139- return None
140+ if type_ == " Faction" :
141+ return get_faction(id_)
142+ if type_ == " Ship" :
143+ return get_ship(id_)
144+ return None # pragma: no cover
140145
141146def get_node_type (obj , _info , _type ):
142147 if isinstance (obj, Faction):
143- return factionType
144- else :
145- return shipType
148+ return faction_type.name
149+ return ship_type.name
146150
147- node_interface, node_field = node_definitions(get_node, get_node_type)
151+ node_interface, node_field = node_definitions(get_node, get_node_type)[: 2 ]
148152
149- factionType = GraphQLObjectType(
150- name = ' Faction' ,
151- description = ' A faction in the Star Wars saga' ,
152- fields = lambda : {
153- ' id' : global_id_field(' Faction' ),
153+ faction_type = GraphQLObjectType(
154+ name = " Faction" ,
155+ description = " A faction in the Star Wars saga" ,
156+ fields = lambda : {
157+ " id" : global_id_field(" Faction" ),
158+ " name" : GraphQLField(GraphQLString, description = " The name of the faction." ),
159+ " ships" : GraphQLField(
160+ ship_connection,
161+ description = " The ships used by the faction." ,
162+ args = connection_args,
163+ resolve = lambda faction , _info , ** args : connection_from_array(
164+ [get_ship(ship) for ship in faction.ships], args
165+ ),
166+ ),
154167 },
155- interfaces = [node_interface]
168+ interfaces = [node_interface],
156169)
157170
158- queryType = GraphQLObjectType(
159- name = ' Query' ,
160- fields = lambda : {
161- ' node' : node_field
162- }
171+ query_type = GraphQLObjectType(
172+ name = " Query" ,
173+ fields = lambda : {
174+ " rebels" : GraphQLField(faction_type, resolve = lambda _obj , _info : get_rebels()),
175+ " empire" : GraphQLField(faction_type, resolve = lambda _obj , _info : get_empire()),
176+ " node" : node_field,
177+ },
163178)
164179```
165180
166181This uses ` node_definitions ` to construct the ` Node ` interface and the ` node `
167- field; it uses ` from_global_id ` to resolve the IDs passed in in the implementation
182+ field; it uses ` from_global_id ` to resolve the IDs passed in the implementation
168183of the function mapping ID to object. It then uses the ` global_id_field ` method to
169184create the ` id ` field on ` Faction ` , which also ensures implements the
170185` node_interface ` . Finally, it adds the ` node ` field to the query type, using the
@@ -184,43 +199,35 @@ An example usage of these methods from the [test schema](tests/star_wars_schema.
184199
185200``` python
186201class IntroduceShipMutation :
202+
187203 def __init__ (self , shipId , factionId , clientMutationId = None ):
188204 self .shipId = shipId
189205 self .factionId = factionId
190206 self .clientMutationId = clientMutationId
191207
192- def mutate_and_get_payload (_info , shipName , factionId ):
193- newShip = createShip (shipName, factionId)
194- return IntroduceShipMutation(shipId = newShip .id, factionId = factionId)
208+ def mutate_and_get_payload (_info , shipName , factionId , ** _input ):
209+ new_ship = create_ship (shipName, factionId)
210+ return IntroduceShipMutation(shipId = new_ship .id, factionId = factionId)
195211
196- shipMutation = mutation_with_client_mutation_id(
197- ' IntroduceShip' ,
212+ ship_mutation = mutation_with_client_mutation_id(
213+ " IntroduceShip" ,
198214 input_fields = {
199- ' shipName' : GraphQLInputField(
200- GraphQLNonNull(GraphQLString)
201- ),
202- ' factionId' : GraphQLInputField(
203- GraphQLNonNull(GraphQLID)
204- )
215+ " shipName" : GraphQLInputField(GraphQLNonNull(GraphQLString)),
216+ " factionId" : GraphQLInputField(GraphQLNonNull(GraphQLID)),
205217 },
206218 output_fields = {
207- ' ship' : GraphQLField(
208- shipType,
209- resolve = lambda payload , _info : getShip(payload.shipId)
219+ " ship" : GraphQLField(
220+ ship_type, resolve = lambda payload , _info : get_ship(payload.shipId)
221+ ),
222+ " faction" : GraphQLField(
223+ faction_type, resolve = lambda payload , _info : get_faction(payload.factionId)
210224 ),
211- ' faction' : GraphQLField(
212- factionType,
213- resolve = lambda payload , _info : getFaction(payload.factionId)
214- )
215225 },
216- mutate_and_get_payload = mutate_and_get_payload
226+ mutate_and_get_payload = mutate_and_get_payload,
217227)
218228
219- mutationType = GraphQLObjectType(
220- ' Mutation' ,
221- fields = lambda : {
222- ' introduceShip' : shipMutation
223- }
229+ mutation_type = GraphQLObjectType(
230+ " Mutation" , fields = lambda : {" introduceShip" : ship_mutation}
224231)
225232```
226233
@@ -268,5 +275,5 @@ Python versions and perform all additional source code checks.
268275You can also restrict tox to an individual environment, like this:
269276
270277``` sh
271- poetry run tox -e py37
278+ poetry run tox -e py39
272279```
0 commit comments