Skip to content

Commit 5cb7d91

Browse files
dvndrsnjkimbo
authored andcommitted
Revise documentation (#969)
* Revise documentation - Add missing reference to `flask-graphql` in integrations - align documentation for resolver arguments (use root for 1st argument instead of self) - explore use of `parent` instead of `root` for first argument - clarify resolvers and object type documentation - add documentation for Meta class options for ObjectType - expand quickstart documentation for first time users - streamline order of documentation for first time users (broad -> specific) - document resolver quirks * explict imports from graphene * rename doc refs for resolvers * suggestions typos and graphene import
1 parent da1359e commit 5cb7d91

13 files changed

+573
-190
lines changed

UPGRADE-v1.0.md

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,29 @@
22

33
Big changes from v0.10.x to 1.0. While on the surface a lot of this just looks like shuffling around API, the entire codebase has been rewritten to handle some really great use cases and improved performance.
44

5-
65
## Backwards Compatibility and Deprecation Warnings
76

87
This has been a community project from the start, we need your help making the upgrade as smooth as possible for everybody!
98
We have done our best to provide backwards compatibility with deprecated APIs.
109

11-
1210
## Deprecations
1311

14-
* `with_context` is no longer needed. Resolvers now always take the context argument.
12+
- `with_context` is no longer needed. Resolvers now always take the context argument.
1513
Before:
1614

1715
```python
18-
def resolve_xxx(self, args, info):
16+
def resolve_xxx(root, args, info):
1917
# ...
2018
```
2119

2220
With 1.0:
21+
2322
```python
24-
def resolve_xxx(self, args, context, info):
23+
def resolve_xxx(root, args, context, info):
2524
# ...
2625
```
2726

28-
* `ObjectType` and `Interface` no longer accept the `abstract` option in the `Meta`.
27+
- `ObjectType` and `Interface` no longer accept the `abstract` option in the `Meta`.
2928
Inheriting fields should be now achieved using `AbstractType` inheritance.
3029

3130
Before:
@@ -42,6 +41,7 @@ We have done our best to provide backwards compatibility with deprecated APIs.
4241
```
4342

4443
With 1.0:
44+
4545
```python
4646
class MyBaseQuery(graphene.AbstractType):
4747
my_field = String()
@@ -50,9 +50,9 @@ We have done our best to provide backwards compatibility with deprecated APIs.
5050
pass
5151
```
5252

53-
* The `type_name` option in the Meta in types is now `name`
53+
- The `type_name` option in the Meta in types is now `name`
5454

55-
* Type references no longer work with strings, but with functions.
55+
- Type references no longer work with strings, but with functions.
5656

5757
Before:
5858

@@ -70,7 +70,6 @@ We have done our best to provide backwards compatibility with deprecated APIs.
7070
users = graphene.List(lambda: User)
7171
```
7272

73-
7473
## Schema
7574

7675
Schemas in graphene `1.0` are `Immutable`, that means that once you create a `graphene.Schema` any
@@ -80,7 +79,6 @@ The `name` argument is removed from the Schema.
8079
The arguments `executor` and `middlewares` are also removed from the `Schema` definition.
8180
You can still use them, but by calling explicitly in the `execute` method in `graphql`.
8281

83-
8482
```python
8583
# Old way
8684
schema = graphene.Schema(name='My Schema')
@@ -94,7 +92,6 @@ schema = graphene.Schema(
9492
)
9593
```
9694

97-
9895
## Interfaces
9996

10097
For implementing an Interface in an ObjectType, you have to add it onto `Meta.interfaces`.
@@ -131,7 +128,7 @@ class ReverseString(Mutation):
131128

132129
reversed = String()
133130

134-
def mutate(self, args, context, info):
131+
def mutate(root, args, context, info):
135132
reversed = args.get('input')[::-1]
136133
return ReverseString(reversed=reversed)
137134

@@ -158,14 +155,13 @@ class Query(ObjectType):
158155
Also, if you wanted to create an `ObjectType` that implements `Node`, you have to do it
159156
explicity.
160157

161-
162158
## Django
163159

164160
The Django integration with Graphene now has an independent package: `graphene-django`.
165161
For installing, you have to replace the old `graphene[django]` with `graphene-django`.
166162

167-
* As the package is now independent, you now have to import from `graphene_django`.
168-
* **DjangoNode no longer exists**, please use `relay.Node` instead:
163+
- As the package is now independent, you now have to import from `graphene_django`.
164+
- **DjangoNode no longer exists**, please use `relay.Node` instead:
169165

170166
```python
171167
from graphene.relay import Node
@@ -181,8 +177,8 @@ For installing, you have to replace the old `graphene[django]` with `graphene-dj
181177
The SQLAlchemy integration with Graphene now has an independent package: `graphene-sqlalchemy`.
182178
For installing, you have to replace the old `graphene[sqlalchemy]` with `graphene-sqlalchemy`.
183179

184-
* As the package is now independent, you have to import now from `graphene_sqlalchemy`.
185-
* **SQLAlchemyNode no longer exists**, please use `relay.Node` instead:
180+
- As the package is now independent, you have to import now from `graphene_sqlalchemy`.
181+
- **SQLAlchemyNode no longer exists**, please use `relay.Node` instead:
186182

187183
```python
188184
from graphene.relay import Node

UPGRADE-v2.0.md

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,22 @@ It also improves the field resolvers, [simplifying the code](#simpler-resolvers)
77
developer has to write to use them.
88

99
**Deprecations:**
10-
* [`AbstractType`](#abstracttype-deprecated)
11-
* [`resolve_only_args`](#resolve_only_args)
12-
* [`Mutation.Input`](#mutationinput)
10+
11+
- [`AbstractType`](#abstracttype-deprecated)
12+
- [`resolve_only_args`](#resolve_only_args)
13+
- [`Mutation.Input`](#mutationinput)
1314

1415
**Breaking changes:**
15-
* [`Simpler Resolvers`](#simpler-resolvers)
16-
* [`Node Connections`](#node-connections)
16+
17+
- [`Simpler Resolvers`](#simpler-resolvers)
18+
- [`Node Connections`](#node-connections)
1719

1820
**New Features!**
19-
* [`InputObjectType`](#inputobjecttype)
20-
* [`Meta as Class arguments`](#meta-as-class-arguments) (_only available for Python 3_)
2121

22+
- [`InputObjectType`](#inputobjecttype)
23+
- [`Meta as Class arguments`](#meta-as-class-arguments) (_only available for Python 3_)
2224

23-
> The type metaclasses are now deleted as they are no longer necessary. If your code was depending
25+
> The type metaclasses are now deleted as they are no longer necessary. If your code was depending
2426
> on this strategy for creating custom attrs, see an [example on how to do it in 2.0](https://github.com/graphql-python/graphene/blob/v2.0.0/graphene/tests/issues/test_425.py).
2527
2628
## Deprecations
@@ -49,7 +51,7 @@ class Pet(CommonFields, Interface):
4951
pass
5052
```
5153

52-
### resolve\_only\_args
54+
### resolve_only_args
5355

5456
`resolve_only_args` is now deprecated as the resolver API has been simplified.
5557

@@ -60,8 +62,8 @@ class User(ObjectType):
6062
name = String()
6163

6264
@resolve_only_args
63-
def resolve_name(self):
64-
return self.name
65+
def resolve_name(root):
66+
return root.name
6567
```
6668

6769
With 2.0:
@@ -70,8 +72,8 @@ With 2.0:
7072
class User(ObjectType):
7173
name = String()
7274

73-
def resolve_name(self, info):
74-
return self.name
75+
def resolve_name(root, info):
76+
return root.name
7577
```
7678

7779
### Mutation.Input
@@ -94,7 +96,6 @@ class User(Mutation):
9496
name = String()
9597
```
9698

97-
9899
## Breaking Changes
99100

100101
### Simpler resolvers
@@ -108,7 +109,7 @@ Before:
108109
```python
109110
my_field = graphene.String(my_arg=graphene.String())
110111

111-
def resolve_my_field(self, args, context, info):
112+
def resolve_my_field(root, args, context, info):
112113
my_arg = args.get('my_arg')
113114
return ...
114115
```
@@ -118,23 +119,23 @@ With 2.0:
118119
```python
119120
my_field = graphene.String(my_arg=graphene.String())
120121

121-
def resolve_my_field(self, info, my_arg):
122+
def resolve_my_field(root, info, my_arg):
122123
return ...
123124
```
124125

125126
**PS.: Take care with receiving args like `my_arg` as above. This doesn't work for optional (non-required) arguments as stantard `Connection`'s arguments (first, before, after, before).**
126127
You may need something like this:
127128

128129
```python
129-
def resolve_my_field(self, info, known_field1, known_field2, **args): ## get other args with: args.get('arg_key')
130+
def resolve_my_field(root, info, known_field1, known_field2, **args): ## get other args with: args.get('arg_key')
130131
```
131132

132133
And, if you need the context in the resolver, you can use `info.context`:
133134

134135
```python
135136
my_field = graphene.String(my_arg=graphene.String())
136137

137-
def resolve_my_field(self, info, my_arg):
138+
def resolve_my_field(root, info, my_arg):
138139
context = info.context
139140
return ...
140141
```
@@ -188,6 +189,7 @@ class MyObject(ObjectType):
188189
```
189190

190191
To:
192+
191193
```python
192194
class MyObject(ObjectType):
193195
class Meta:
@@ -203,30 +205,32 @@ class MyObject(ObjectType):
203205
The parameters' order of `get_node_from_global_id` method has changed. You may need to adjust your [Node Root Field](http://docs.graphene-python.org/en/latest/relay/nodes/#node-root-field) and maybe other places that uses this method to obtain an object.
204206

205207
Before:
208+
206209
```python
207210
class RootQuery(object):
208211
...
209212
node = Field(relay.Node, id=ID(required=True))
210213

211-
def resolve_node(self, args, context, info):
214+
def resolve_node(root, args, context, info):
212215
node = relay.Node.get_node_from_global_id(args['id'], context, info)
213216
return node
214217
```
215218

216219
Now:
220+
217221
```python
218222
class RootQuery(object):
219223
...
220224
node = Field(relay.Node, id=ID(required=True))
221225

222-
def resolve_node(self, info, id):
226+
def resolve_node(root, info, id):
223227
node = relay.Node.get_node_from_global_id(info, id)
224228
return node
225229
```
226230

227231
## Mutation.mutate
228232

229-
Now only receives (`self`, `info`, `**args`) and is not a @classmethod
233+
Now only receives (`root`, `info`, `**kwargs`) and is not a @classmethod
230234

231235
Before:
232236

@@ -245,7 +249,7 @@ With 2.0:
245249
class SomeMutation(Mutation):
246250
...
247251

248-
def mutate(self, info, **args):
252+
def mutate(root, info, **args):
249253
...
250254
```
251255

@@ -258,17 +262,14 @@ class SomeMutation(Mutation):
258262
last_name = String(required=True)
259263
...
260264

261-
def mutate(self, info, first_name, last_name):
265+
def mutate(root, info, first_name, last_name):
262266
...
263267
```
264268

265-
266-
267269
## ClientIDMutation.mutate_and_get_payload
268270

269271
Now only receives (`root`, `info`, `**input`)
270272

271-
272273
### Middlewares
273274

274275
If you are using Middelwares, you need to some adjustments:
@@ -294,10 +295,9 @@ class MyGrapheneMiddleware(object):
294295
## Middleware code
295296

296297
info.context = context
297-
       return next_mw(root, info, **args)```
298+
       return next_mw(root, info, **args)
298299
```
299300

300-
301301
## New Features
302302

303303
### InputObjectType
@@ -321,7 +321,7 @@ class Query(ObjectType):
321321
user = graphene.Field(User, input=UserInput())
322322

323323
@resolve_only_args
324-
def resolve_user(self, input):
324+
def resolve_user(root, input):
325325
user_id = input.get('id')
326326
if is_valid_input(user_id):
327327
return get_user(user_id)
@@ -334,18 +334,17 @@ class UserInput(InputObjectType):
334334
id = ID(required=True)
335335

336336
@property
337-
def is_valid(self):
338-
return self.id.startswith('userid_')
337+
def is_valid(root):
338+
return root.id.startswith('userid_')
339339

340340
class Query(ObjectType):
341341
user = graphene.Field(User, input=UserInput())
342342

343-
def resolve_user(self, info, input):
343+
def resolve_user(root, info, input):
344344
if input.is_valid:
345345
return get_user(input.id)
346346
```
347347

348-
349348
### Meta as Class arguments
350349

351350
Now you can use the meta options as class arguments (**ONLY PYTHON 3**).
@@ -366,7 +365,6 @@ class Dog(ObjectType, interfaces=[Pet]):
366365
name = String()
367366
```
368367

369-
370368
### Abstract types
371369

372370
Now you can create abstact types super easily, without the need of subclassing the meta.
@@ -378,10 +376,10 @@ class Base(ObjectType):
378376

379377
id = ID()
380378

381-
def resolve_id(self, info):
379+
def resolve_id(root, info):
382380
return "{type}_{id}".format(
383-
type=self.__class__.__name__,
384-
id=self.id
381+
type=root.__class__.__name__,
382+
id=root.id
385383
)
386384
```
387385

docs/execution/dataloader.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ leaner code and at most 4 database requests, and possibly fewer if there are cac
111111
best_friend = graphene.Field(lambda: User)
112112
friends = graphene.List(lambda: User)
113113
114-
def resolve_best_friend(self, info):
115-
return user_loader.load(self.best_friend_id)
114+
def resolve_best_friend(root, info):
115+
return user_loader.load(root.best_friend_id)
116116
117-
def resolve_friends(self, info):
118-
return user_loader.load_many(self.friend_ids)
117+
def resolve_friends(root, info):
118+
return user_loader.load_many(root.friend_ids)

0 commit comments

Comments
 (0)