Skip to content

Commit

Permalink
Revise documentation (#969)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
dvndrsn authored and jkimbo committed Jun 9, 2019
1 parent da1359e commit 5cb7d91
Show file tree
Hide file tree
Showing 13 changed files with 573 additions and 190 deletions.
30 changes: 13 additions & 17 deletions UPGRADE-v1.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,29 @@

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.


## Backwards Compatibility and Deprecation Warnings

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


## Deprecations

* `with_context` is no longer needed. Resolvers now always take the context argument.
- `with_context` is no longer needed. Resolvers now always take the context argument.
Before:

```python
def resolve_xxx(self, args, info):
def resolve_xxx(root, args, info):
# ...
```

With 1.0:

```python
def resolve_xxx(self, args, context, info):
def resolve_xxx(root, args, context, info):
# ...
```

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

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

With 1.0:

```python
class MyBaseQuery(graphene.AbstractType):
my_field = String()
Expand All @@ -50,9 +50,9 @@ We have done our best to provide backwards compatibility with deprecated APIs.
pass
```

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

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

Before:

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


## Schema

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


```python
# Old way
schema = graphene.Schema(name='My Schema')
Expand All @@ -94,7 +92,6 @@ schema = graphene.Schema(
)
```


## Interfaces

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

reversed = String()

def mutate(self, args, context, info):
def mutate(root, args, context, info):
reversed = args.get('input')[::-1]
return ReverseString(reversed=reversed)

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


## Django

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

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

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

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

```python
from graphene.relay import Node
Expand Down
72 changes: 35 additions & 37 deletions UPGRADE-v2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ It also improves the field resolvers, [simplifying the code](#simpler-resolvers)
developer has to write to use them.

**Deprecations:**
* [`AbstractType`](#abstracttype-deprecated)
* [`resolve_only_args`](#resolve_only_args)
* [`Mutation.Input`](#mutationinput)

- [`AbstractType`](#abstracttype-deprecated)
- [`resolve_only_args`](#resolve_only_args)
- [`Mutation.Input`](#mutationinput)

**Breaking changes:**
* [`Simpler Resolvers`](#simpler-resolvers)
* [`Node Connections`](#node-connections)

- [`Simpler Resolvers`](#simpler-resolvers)
- [`Node Connections`](#node-connections)

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

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

> The type metaclasses are now deleted as they are no longer necessary. If your code was depending
> The type metaclasses are now deleted as they are no longer necessary. If your code was depending
> 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).
## Deprecations
Expand Down Expand Up @@ -49,7 +51,7 @@ class Pet(CommonFields, Interface):
pass
```

### resolve\_only\_args
### resolve_only_args

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

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

@resolve_only_args
def resolve_name(self):
return self.name
def resolve_name(root):
return root.name
```

With 2.0:
Expand All @@ -70,8 +72,8 @@ With 2.0:
class User(ObjectType):
name = String()

def resolve_name(self, info):
return self.name
def resolve_name(root, info):
return root.name
```

### Mutation.Input
Expand All @@ -94,7 +96,6 @@ class User(Mutation):
name = String()
```


## Breaking Changes

### Simpler resolvers
Expand All @@ -108,7 +109,7 @@ Before:
```python
my_field = graphene.String(my_arg=graphene.String())

def resolve_my_field(self, args, context, info):
def resolve_my_field(root, args, context, info):
my_arg = args.get('my_arg')
return ...
```
Expand All @@ -118,23 +119,23 @@ With 2.0:
```python
my_field = graphene.String(my_arg=graphene.String())

def resolve_my_field(self, info, my_arg):
def resolve_my_field(root, info, my_arg):
return ...
```

**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).**
You may need something like this:

```python
def resolve_my_field(self, info, known_field1, known_field2, **args): ## get other args with: args.get('arg_key')
def resolve_my_field(root, info, known_field1, known_field2, **args): ## get other args with: args.get('arg_key')
```

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

```python
my_field = graphene.String(my_arg=graphene.String())

def resolve_my_field(self, info, my_arg):
def resolve_my_field(root, info, my_arg):
context = info.context
return ...
```
Expand Down Expand Up @@ -188,6 +189,7 @@ class MyObject(ObjectType):
```

To:

```python
class MyObject(ObjectType):
class Meta:
Expand All @@ -203,30 +205,32 @@ class MyObject(ObjectType):
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.

Before:

```python
class RootQuery(object):
...
node = Field(relay.Node, id=ID(required=True))

def resolve_node(self, args, context, info):
def resolve_node(root, args, context, info):
node = relay.Node.get_node_from_global_id(args['id'], context, info)
return node
```

Now:

```python
class RootQuery(object):
...
node = Field(relay.Node, id=ID(required=True))

def resolve_node(self, info, id):
def resolve_node(root, info, id):
node = relay.Node.get_node_from_global_id(info, id)
return node
```

## Mutation.mutate

Now only receives (`self`, `info`, `**args`) and is not a @classmethod
Now only receives (`root`, `info`, `**kwargs`) and is not a @classmethod

Before:

Expand All @@ -245,7 +249,7 @@ With 2.0:
class SomeMutation(Mutation):
...

def mutate(self, info, **args):
def mutate(root, info, **args):
...
```

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

def mutate(self, info, first_name, last_name):
def mutate(root, info, first_name, last_name):
...
```



## ClientIDMutation.mutate_and_get_payload

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


### Middlewares

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

info.context = context
       return next_mw(root, info, **args)```
       return next_mw(root, info, **args)
```

## New Features

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

@resolve_only_args
def resolve_user(self, input):
def resolve_user(root, input):
user_id = input.get('id')
if is_valid_input(user_id):
return get_user(user_id)
Expand All @@ -334,18 +334,17 @@ class UserInput(InputObjectType):
id = ID(required=True)

@property
def is_valid(self):
return self.id.startswith('userid_')
def is_valid(root):
return root.id.startswith('userid_')

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

def resolve_user(self, info, input):
def resolve_user(root, info, input):
if input.is_valid:
return get_user(input.id)
```


### Meta as Class arguments

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


### Abstract types

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

id = ID()

def resolve_id(self, info):
def resolve_id(root, info):
return "{type}_{id}".format(
type=self.__class__.__name__,
id=self.id
type=root.__class__.__name__,
id=root.id
)
```

Expand Down
8 changes: 4 additions & 4 deletions docs/execution/dataloader.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ leaner code and at most 4 database requests, and possibly fewer if there are cac
best_friend = graphene.Field(lambda: User)
friends = graphene.List(lambda: User)
def resolve_best_friend(self, info):
return user_loader.load(self.best_friend_id)
def resolve_best_friend(root, info):
return user_loader.load(root.best_friend_id)
def resolve_friends(self, info):
return user_loader.load_many(self.friend_ids)
def resolve_friends(root, info):
return user_loader.load_many(root.friend_ids)
Loading

0 comments on commit 5cb7d91

Please sign in to comment.