mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 12:44:15 +03:00
Added ability to skip fields in runtime
This commit is contained in:
parent
3f9b94b73f
commit
25eca8776a
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
10
graphene/core/scalars.py
Normal 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)
|
|
@ -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)
|
||||
|
|
|
@ -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 '
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue
Block a user