Added ability to skip fields in runtime

This commit is contained in:
Syrus Akbary 2015-10-03 16:48:18 -07:00
parent 3f9b94b73f
commit 25eca8776a
8 changed files with 40 additions and 17 deletions

View File

@ -65,14 +65,18 @@ class DjangoModelField(Field):
@memoize
def internal_type(self, schema):
_type = self.get_object_type(schema)
return _type and _type.internal_type(schema)
if not _type and self.object_type._meta.only_fields:
raise Exception(
"Model %r is not accessible by the schema. "
"You can either register the type manually "
"using @schema.register. "
"Or disable the field %s in %s" % (
self.model,
self.field_name,
self.object_type
)
)
return _type and _type.internal_type(schema) or Field.SKIP
def get_object_type(self, schema):
_type = get_type_for_model(schema, self.model)
if not _type and self.object_type._meta.only_fields:
# We will only raise the exception if the related field is
# specified in only_fields
raise Exception("Field %s (%s) model not mapped in current schema" % (
self, self.model._meta.object_name))
return _type
return get_type_for_model(schema, self.model)

View File

@ -46,4 +46,7 @@ class DjangoInterface(six.with_metaclass(DjangoObjectTypeMeta, BaseObjectType)):
class DjangoNode(BaseNode, DjangoInterface):
pass
@classmethod
def get_node(cls, id):
instance = cls._meta.model.objects.filter(id=id).first()
return cls(instance)

View File

@ -12,9 +12,11 @@ from graphql.core.type import (
)
from graphene.utils import memoize, to_camel_case
from graphene.core.types import BaseObjectType
from graphene.core.scalars import GraphQLSkipField
class Field(object):
SKIP = GraphQLSkipField
def __init__(self, field_type, name=None, resolve=None, null=True, args=None, description='', **extra_args):
self.field_type = field_type
@ -95,7 +97,8 @@ class Field(object):
))
internal_type = self.internal_type(schema)
if not internal_type:
raise Exception("Internal type for field %s is None" % self)
return GraphQLField(
internal_type,
description=self.description,
@ -111,7 +114,7 @@ class Field(object):
"""
Displays the module, class and name of the field.
"""
path = '%s.%s' % (self.__class__.__module__, self.__class__.__name__)
path = '%r.%s' % (self.object_type, self.__class__.__name__)
name = getattr(self, 'field_name', None)
if name is not None:
return '<%s: %s>' % (path, name)

10
graphene/core/scalars.py Normal file
View File

@ -0,0 +1,10 @@
from graphql.core.type.definition import GraphQLScalarType
def skip(value):
return None
GraphQLSkipField = GraphQLScalarType(name='SkipField',
serialize=skip,
parse_value=skip,
parse_literal=skip)

View File

@ -45,6 +45,10 @@ class Schema(object):
def associate_internal_type(self, internal_type, object_type):
self._internal_types[internal_type.name] = object_type
def register(self, object_type):
self._internal_types[object_type._meta.type_name] = object_type
return object_type
def get_type(self, type_name):
# print 'get_type'
# _type = self.schema.get_type(type_name)

View File

@ -49,7 +49,7 @@ class ObjectTypeMeta(type):
new_class.add_extra_fields()
new_fields = new_class._meta.local_fields
field_names = {f.name for f in new_fields}
field_names = {f.name:f for f in new_fields}
for base in parents:
original_base = base
@ -65,7 +65,7 @@ class ObjectTypeMeta(type):
# on the base classes (we cannot handle shadowed fields at the
# moment).
for field in parent_fields:
if field.name in field_names:
if field.name in field_names and field.__class__ != field_names[field].__class__:
raise Exception(
'Local field %r in class %r clashes '
'with field of similar name from '

View File

@ -19,6 +19,8 @@ def get_node(schema, globalId, *args):
resolvedGlobalId = fromGlobalId(globalId)
_type, _id = resolvedGlobalId.type, resolvedGlobalId.id
object_type = schema.get_type(_type)
if not object_type or not issubclass(object_type, BaseNode):
raise Exception("The type %s is not a Node" % _type)
return object_type.get_node(_id)

View File

@ -43,9 +43,6 @@ def test_should_raise_if_model_is_invalid():
result = schema.execute(query)
assert not result.errors
assert 'articles (Article) model not mapped in current schema' in str(
excinfo.value)
def test_should_map_fields_correctly():
class ReporterType2(DjangoObjectType):