@@ -63,47 +63,53 @@ from graphql_relay import connection_definitions
63
63
### Connections
64
64
65
65
Helper 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
67
67
returning those types.
68
68
69
69
- ` 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.
71
75
- ` connection_definitions ` returns a ` connection_type ` and its associated
72
76
` edgeType ` , given a name and a node type.
73
77
- ` connection_from_array ` is a helper method that takes an array and the
74
78
arguments 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.
76
80
- ` cursor_for_object_in_connection ` is a helper method that takes an array and a
77
81
member 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.
78
86
79
87
An example usage of these methods from the [ test schema] ( tests/star_wars_schema.py ) :
80
88
81
89
``` python
82
- ship_edge, ship_connection = connection_definitions(' Ship ' , shipType )
90
+ ship_edge, ship_connection = connection_definitions(ship_type, " Ship " )
83
91
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" ,
87
95
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(
94
99
ship_connection,
95
- description = ' The ships used by the faction.' ,
100
+ description = " The ships used by the faction." ,
96
101
args = connection_args,
97
102
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
+ ),
100
106
},
101
- interfaces = [node_interface]
107
+ interfaces = [node_interface],
102
108
)
103
109
```
104
110
105
111
This 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
107
113
type, adds ` connection_args ` as arguments on this function, and then implements
108
114
the resolver function by passing the array of ships and the arguments to
109
115
` connection_from_array ` .
@@ -131,40 +137,49 @@ An example usage of these methods from the [test schema](tests/star_wars_schema.
131
137
``` python
132
138
def get_node (global_id , _info ):
133
139
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
140
145
141
146
def get_node_type (obj , _info , _type ):
142
147
if isinstance (obj, Faction):
143
- return factionType
144
- else :
145
- return shipType
148
+ return faction_type.name
149
+ return ship_type.name
146
150
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 ]
148
152
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
+ ),
154
167
},
155
- interfaces = [node_interface]
168
+ interfaces = [node_interface],
156
169
)
157
170
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
+ },
163
178
)
164
179
```
165
180
166
181
This 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
168
183
of the function mapping ID to object. It then uses the ` global_id_field ` method to
169
184
create the ` id ` field on ` Faction ` , which also ensures implements the
170
185
` 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.
184
199
185
200
``` python
186
201
class IntroduceShipMutation :
202
+
187
203
def __init__ (self , shipId , factionId , clientMutationId = None ):
188
204
self .shipId = shipId
189
205
self .factionId = factionId
190
206
self .clientMutationId = clientMutationId
191
207
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)
195
211
196
- shipMutation = mutation_with_client_mutation_id(
197
- ' IntroduceShip' ,
212
+ ship_mutation = mutation_with_client_mutation_id(
213
+ " IntroduceShip" ,
198
214
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)),
205
217
},
206
218
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)
210
224
),
211
- ' faction' : GraphQLField(
212
- factionType,
213
- resolve = lambda payload , _info : getFaction(payload.factionId)
214
- )
215
225
},
216
- mutate_and_get_payload = mutate_and_get_payload
226
+ mutate_and_get_payload = mutate_and_get_payload,
217
227
)
218
228
219
- mutationType = GraphQLObjectType(
220
- ' Mutation' ,
221
- fields = lambda : {
222
- ' introduceShip' : shipMutation
223
- }
229
+ mutation_type = GraphQLObjectType(
230
+ " Mutation" , fields = lambda : {" introduceShip" : ship_mutation}
224
231
)
225
232
```
226
233
@@ -268,5 +275,5 @@ Python versions and perform all additional source code checks.
268
275
You can also restrict tox to an individual environment, like this:
269
276
270
277
``` sh
271
- poetry run tox -e py37
278
+ poetry run tox -e py39
272
279
```
0 commit comments