mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-08 23:50:38 +03:00
First working version of mutations
This commit is contained in:
parent
9e101898f1
commit
2648a2300b
|
@ -14,7 +14,8 @@ from graphene.core.schema import (
|
||||||
|
|
||||||
from graphene.core.types import (
|
from graphene.core.types import (
|
||||||
ObjectType,
|
ObjectType,
|
||||||
Interface
|
Interface,
|
||||||
|
Mutation,
|
||||||
)
|
)
|
||||||
|
|
||||||
from graphene.core.fields import (
|
from graphene.core.fields import (
|
||||||
|
@ -31,3 +32,8 @@ from graphene.core.fields import (
|
||||||
from graphene.decorators import (
|
from graphene.decorators import (
|
||||||
resolve_only_args
|
resolve_only_args
|
||||||
)
|
)
|
||||||
|
|
||||||
|
__all__ = ['Enum', 'Argument', 'String', 'Int', 'ID', 'signals', 'Schema',
|
||||||
|
'ObjectType', 'Interface', 'Mutation', 'Field', 'StringField',
|
||||||
|
'IntField', 'BooleanField', 'IDField', 'ListField', 'NonNullField',
|
||||||
|
'FloatField', 'resolve_only_args']
|
||||||
|
|
|
@ -51,14 +51,18 @@ class Field(object):
|
||||||
cls._meta.add_field(self)
|
cls._meta.add_field(self)
|
||||||
|
|
||||||
def resolve(self, instance, args, info):
|
def resolve(self, instance, args, info):
|
||||||
resolve_fn = self.get_resolve_fn()
|
schema = info and getattr(info.schema, 'graphene_schema', None)
|
||||||
|
resolve_fn = self.get_resolve_fn(schema)
|
||||||
if resolve_fn:
|
if resolve_fn:
|
||||||
return resolve_fn(instance, args, info)
|
return resolve_fn(instance, args, info)
|
||||||
else:
|
else:
|
||||||
return getattr(instance, self.field_name, None)
|
return getattr(instance, self.field_name, None)
|
||||||
|
|
||||||
def get_resolve_fn(self):
|
def get_resolve_fn(self, schema):
|
||||||
if self.resolve_fn:
|
object_type = self.get_object_type(schema)
|
||||||
|
if object_type and object_type._meta.mutation:
|
||||||
|
return object_type.mutate
|
||||||
|
elif self.resolve_fn:
|
||||||
return self.resolve_fn
|
return self.resolve_fn
|
||||||
else:
|
else:
|
||||||
custom_resolve_fn_name = 'resolve_%s' % self.field_name
|
custom_resolve_fn_name = 'resolve_%s' % self.field_name
|
||||||
|
@ -125,7 +129,7 @@ class Field(object):
|
||||||
raise Exception("Internal type for field %s is None" % self)
|
raise Exception("Internal type for field %s is None" % self)
|
||||||
|
|
||||||
description = self.description
|
description = self.description
|
||||||
resolve_fn = self.get_resolve_fn()
|
resolve_fn = self.get_resolve_fn(schema)
|
||||||
if resolve_fn:
|
if resolve_fn:
|
||||||
description = resolve_fn.__doc__ or description
|
description = resolve_fn.__doc__ or description
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from graphene.utils import cached_property
|
from graphene.utils import cached_property
|
||||||
from collections import OrderedDict, namedtuple
|
from collections import OrderedDict, namedtuple
|
||||||
|
|
||||||
DEFAULT_NAMES = ('description', 'name', 'interface',
|
DEFAULT_NAMES = ('description', 'name', 'interface', 'mutation',
|
||||||
'type_name', 'interfaces', 'proxy')
|
'type_name', 'interfaces', 'proxy')
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ class Options(object):
|
||||||
self.meta = meta
|
self.meta = meta
|
||||||
self.local_fields = []
|
self.local_fields = []
|
||||||
self.interface = False
|
self.interface = False
|
||||||
|
self.mutation = False
|
||||||
self.proxy = False
|
self.proxy = False
|
||||||
self.interfaces = []
|
self.interfaces = []
|
||||||
self.parents = []
|
self.parents = []
|
||||||
|
|
|
@ -43,6 +43,15 @@ class Schema(object):
|
||||||
self._query = query
|
self._query = query
|
||||||
self._query_type = query and query.internal_type(self)
|
self._query_type = query and query.internal_type(self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mutation(self):
|
||||||
|
return self._mutation
|
||||||
|
|
||||||
|
@mutation.setter
|
||||||
|
def mutation(self, mutation):
|
||||||
|
self._mutation = mutation
|
||||||
|
self._mutation_type = mutation and mutation.internal_type(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def executor(self):
|
def executor(self):
|
||||||
if not self._executor:
|
if not self._executor:
|
||||||
|
@ -57,7 +66,7 @@ class Schema(object):
|
||||||
def schema(self):
|
def schema(self):
|
||||||
if not self._query_type:
|
if not self._query_type:
|
||||||
raise Exception('You have to define a base query type')
|
raise Exception('You have to define a base query type')
|
||||||
return GraphQLSchema(self, query=self._query_type, mutation=self.mutation)
|
return GraphQLSchema(self, query=self._query_type, mutation=self._mutation_type)
|
||||||
|
|
||||||
def associate_internal_type(self, internal_type, object_type):
|
def associate_internal_type(self, internal_type, object_type):
|
||||||
self._internal_types[internal_type.name] = object_type
|
self._internal_types[internal_type.name] = object_type
|
||||||
|
|
|
@ -55,6 +55,10 @@ class ObjectTypeMeta(type):
|
||||||
# Add all attributes to the class.
|
# Add all attributes to the class.
|
||||||
for obj_name, obj in attrs.items():
|
for obj_name, obj in attrs.items():
|
||||||
new_class.add_to_class(obj_name, obj)
|
new_class.add_to_class(obj_name, obj)
|
||||||
|
|
||||||
|
if new_class._meta.mutation:
|
||||||
|
assert hasattr(new_class, 'mutate'), "All mutations must implement mutate method"
|
||||||
|
|
||||||
new_class.add_extra_fields()
|
new_class.add_extra_fields()
|
||||||
|
|
||||||
new_fields = new_class._meta.local_fields
|
new_fields = new_class._meta.local_fields
|
||||||
|
|
|
@ -87,7 +87,7 @@ def test_field_resolve():
|
||||||
f = StringField(required=True, resolve=lambda *args: 'RESOLVED')
|
f = StringField(required=True, resolve=lambda *args: 'RESOLVED')
|
||||||
f.contribute_to_class(ot, 'field_name')
|
f.contribute_to_class(ot, 'field_name')
|
||||||
field_type = f.internal_field(schema)
|
field_type = f.internal_field(schema)
|
||||||
assert 'RESOLVED' == field_type.resolver(ot, 2, 3)
|
assert 'RESOLVED' == field_type.resolver(ot, None, None)
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve_type_custom():
|
def test_field_resolve_type_custom():
|
||||||
|
|
54
tests/core/test_mutations.py
Normal file
54
tests/core/test_mutations.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import graphene
|
||||||
|
from py.test import raises
|
||||||
|
from graphene.core.schema import Schema
|
||||||
|
|
||||||
|
my_id = 0
|
||||||
|
|
||||||
|
|
||||||
|
class Query(graphene.ObjectType):
|
||||||
|
base = graphene.StringField()
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeNumber(graphene.Mutation):
|
||||||
|
'''Result mutation'''
|
||||||
|
class Input:
|
||||||
|
id = graphene.IntField(required=True)
|
||||||
|
|
||||||
|
result = graphene.StringField()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mutate(cls, instance, args, info):
|
||||||
|
global my_id
|
||||||
|
my_id = my_id + 1
|
||||||
|
return ChangeNumber(result=my_id)
|
||||||
|
|
||||||
|
|
||||||
|
class MyResultMutation(graphene.ObjectType):
|
||||||
|
change_number = graphene.Field(ChangeNumber)
|
||||||
|
|
||||||
|
|
||||||
|
schema = Schema(query=Query, mutation=MyResultMutation)
|
||||||
|
|
||||||
|
|
||||||
|
def test_mutate():
|
||||||
|
query = '''
|
||||||
|
mutation M{
|
||||||
|
first: changeNumber {
|
||||||
|
result
|
||||||
|
},
|
||||||
|
second: changeNumber {
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
expected = {
|
||||||
|
'first': {
|
||||||
|
'result': '1',
|
||||||
|
},
|
||||||
|
'second': {
|
||||||
|
'result': '2',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = schema.execute(query, root=object())
|
||||||
|
assert not result.errors
|
||||||
|
assert result.data == expected
|
|
@ -50,7 +50,7 @@ Human_type = Human.internal_type(schema)
|
||||||
|
|
||||||
|
|
||||||
def test_type():
|
def test_type():
|
||||||
assert Human._meta.fields_map['name'].resolve(Human(object()), 1, 2) == 'Peter'
|
assert Human._meta.fields_map['name'].resolve(Human(object()), None, None) == 'Peter'
|
||||||
|
|
||||||
|
|
||||||
def test_query():
|
def test_query():
|
||||||
|
|
Loading…
Reference in New Issue
Block a user