mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 20:54:16 +03:00
Simplified how NodeIDField is managed. Improved tests
This commit is contained in:
parent
9b2b6ebd06
commit
cafcd89e57
|
@ -24,6 +24,8 @@ class DjangoOptions(Options):
|
||||||
|
|
||||||
def contribute_to_class(self, cls, name):
|
def contribute_to_class(self, cls, name):
|
||||||
super(DjangoOptions, self).contribute_to_class(cls, name)
|
super(DjangoOptions, self).contribute_to_class(cls, name)
|
||||||
|
if is_node(cls):
|
||||||
|
self.exclude_fields += ['id']
|
||||||
if not is_node(cls) and not is_base(cls):
|
if not is_node(cls) and not is_base(cls):
|
||||||
return
|
return
|
||||||
if not self.model:
|
if not self.model:
|
||||||
|
|
|
@ -6,6 +6,7 @@ from graphene.contrib.django.options import DjangoOptions
|
||||||
from graphene.contrib.django.converter import convert_django_field
|
from graphene.contrib.django.converter import convert_django_field
|
||||||
|
|
||||||
from graphene.relay.types import Node, BaseNode
|
from graphene.relay.types import Node, BaseNode
|
||||||
|
from graphene.relay.fields import NodeIDField
|
||||||
|
|
||||||
|
|
||||||
def get_reverse_fields(model):
|
def get_reverse_fields(model):
|
||||||
|
@ -50,6 +51,8 @@ class DjangoInterface(six.with_metaclass(DjangoObjectTypeMeta, BaseObjectType)):
|
||||||
|
|
||||||
|
|
||||||
class DjangoNode(BaseNode, DjangoInterface):
|
class DjangoNode(BaseNode, DjangoInterface):
|
||||||
|
id = NodeIDField()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_node(cls, id):
|
def get_node(cls, id):
|
||||||
instance = cls._meta.model.objects.filter(id=id).first()
|
instance = cls._meta.model.objects.filter(id=id).first()
|
||||||
|
|
|
@ -25,11 +25,12 @@ class Empty(object):
|
||||||
class Field(object):
|
class Field(object):
|
||||||
SKIP = GraphQLSkipField
|
SKIP = GraphQLSkipField
|
||||||
creation_counter = 0
|
creation_counter = 0
|
||||||
|
required = False
|
||||||
|
|
||||||
def __init__(self, field_type, name=None, resolve=None, required=False, args=None, description='', **extra_args):
|
def __init__(self, field_type, name=None, resolve=None, required=False, args=None, description='', **extra_args):
|
||||||
self.field_type = field_type
|
self.field_type = field_type
|
||||||
self.resolve_fn = resolve
|
self.resolve_fn = resolve
|
||||||
self.required = required
|
self.required = self.required or required
|
||||||
self.args = args or {}
|
self.args = args or {}
|
||||||
self.extra_args = extra_args
|
self.extra_args = extra_args
|
||||||
self._type = None
|
self._type = None
|
||||||
|
@ -39,14 +40,15 @@ class Field(object):
|
||||||
self.creation_counter = Field.creation_counter
|
self.creation_counter = Field.creation_counter
|
||||||
Field.creation_counter += 1
|
Field.creation_counter += 1
|
||||||
|
|
||||||
def contribute_to_class(self, cls, name):
|
def contribute_to_class(self, cls, name, add=True):
|
||||||
if not self.name:
|
if not self.name:
|
||||||
self.name = to_camel_case(name)
|
self.name = to_camel_case(name)
|
||||||
self.field_name = name
|
self.field_name = name
|
||||||
self.object_type = cls
|
self.object_type = cls
|
||||||
if isinstance(self.field_type, Field) and not self.field_type.object_type:
|
if isinstance(self.field_type, Field) and not self.field_type.object_type:
|
||||||
self.field_type.contribute_to_class(cls, name)
|
self.field_type.contribute_to_class(cls, name, False)
|
||||||
cls._meta.add_field(self)
|
if add:
|
||||||
|
cls._meta.add_field(self)
|
||||||
|
|
||||||
def resolve(self, instance, args, info):
|
def resolve(self, instance, args, info):
|
||||||
resolve_fn = self.get_resolve_fn()
|
resolve_fn = self.get_resolve_fn()
|
||||||
|
|
|
@ -75,13 +75,13 @@ class ObjectTypeMeta(type):
|
||||||
for field in parent_fields:
|
for field in parent_fields:
|
||||||
if field.name in field_names and field.__class__ != field_names[field.name].__class__:
|
if field.name in field_names and field.__class__ != field_names[field.name].__class__:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Local field %r in class %r clashes '
|
'Local field %r in class %r (%r) clashes '
|
||||||
'with field with similar name from '
|
'with field with similar name from '
|
||||||
'Interface %s (%r != %r)' % (
|
'Interface %s (%r)' % (
|
||||||
field.name,
|
field.name,
|
||||||
new_class.__name__,
|
new_class.__name__,
|
||||||
base.__name__,
|
|
||||||
field.__class__,
|
field.__class__,
|
||||||
|
base.__name__,
|
||||||
field_names[field.name].__class__)
|
field_names[field.name].__class__)
|
||||||
)
|
)
|
||||||
new_field = copy.copy(field)
|
new_field = copy.copy(field)
|
||||||
|
@ -99,6 +99,8 @@ class ObjectTypeMeta(type):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _prepare(cls):
|
def _prepare(cls):
|
||||||
|
if hasattr(cls, '_prepare_class'):
|
||||||
|
cls._prepare_class()
|
||||||
signals.class_prepared.send(cls)
|
signals.class_prepared.send(cls)
|
||||||
|
|
||||||
def add_to_class(cls, name, value):
|
def add_to_class(cls, name, value):
|
||||||
|
|
|
@ -3,8 +3,6 @@ from graphene.relay.fields import (
|
||||||
NodeField
|
NodeField
|
||||||
)
|
)
|
||||||
|
|
||||||
import graphene.relay.connections
|
|
||||||
|
|
||||||
from graphene.relay.types import (
|
from graphene.relay.types import (
|
||||||
Node
|
Node
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
from graphql_relay.node.node import (
|
|
||||||
global_id_field
|
|
||||||
)
|
|
||||||
|
|
||||||
from graphene import signals
|
|
||||||
from graphene.relay.fields import NodeIDField
|
|
||||||
from graphene.relay.utils import is_node
|
|
||||||
|
|
||||||
|
|
||||||
@signals.class_prepared.connect
|
|
||||||
def object_type_created(object_type):
|
|
||||||
if is_node(object_type):
|
|
||||||
type_name = object_type._meta.type_name
|
|
||||||
field = NodeIDField()
|
|
||||||
object_type.add_to_class('id', field)
|
|
||||||
assert hasattr(
|
|
||||||
object_type, 'get_node'), 'get_node classmethod not found in %s Node' % type_name
|
|
|
@ -8,10 +8,11 @@ from graphql_relay.connection.connection import (
|
||||||
)
|
)
|
||||||
from graphql_relay.node.node import (
|
from graphql_relay.node.node import (
|
||||||
global_id_field,
|
global_id_field,
|
||||||
|
to_global_id,
|
||||||
from_global_id
|
from_global_id
|
||||||
)
|
)
|
||||||
|
|
||||||
from graphene.core.fields import Field, LazyNativeField, LazyField
|
from graphene.core.fields import Field, LazyNativeField, IDField
|
||||||
from graphene.utils import cached_property
|
from graphene.utils import cached_property
|
||||||
from graphene.utils import memoize
|
from graphene.utils import memoize
|
||||||
|
|
||||||
|
@ -70,6 +71,9 @@ class NodeField(LazyNativeField):
|
||||||
return BaseNode.get_definitions(schema).node_field
|
return BaseNode.get_definitions(schema).node_field
|
||||||
|
|
||||||
|
|
||||||
class NodeIDField(LazyNativeField):
|
class NodeIDField(IDField):
|
||||||
def get_field(self, schema):
|
required = True
|
||||||
return global_id_field(self.object_type._meta.type_name)
|
|
||||||
|
def resolve(self, instance, args, info):
|
||||||
|
type_name = self.object_type._meta.type_name
|
||||||
|
return to_global_id(type_name, instance.id)
|
||||||
|
|
|
@ -8,6 +8,7 @@ from graphql_relay.connection.connection import (
|
||||||
|
|
||||||
from graphene.core.types import Interface
|
from graphene.core.types import Interface
|
||||||
from graphene.core.fields import LazyNativeField
|
from graphene.core.fields import LazyNativeField
|
||||||
|
from graphene.relay.fields import NodeIDField
|
||||||
from graphene.utils import memoize
|
from graphene.utils import memoize
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +48,13 @@ class BaseNode(object):
|
||||||
return BaseNode.get_definitions(schema).node_interface
|
return BaseNode.get_definitions(schema).node_interface
|
||||||
return super(BaseNode, cls).internal_type(schema)
|
return super(BaseNode, cls).internal_type(schema)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _prepare_class(cls):
|
||||||
|
from graphene.relay.utils import is_node
|
||||||
|
if is_node(cls):
|
||||||
|
assert hasattr(
|
||||||
|
cls, 'get_node'), 'get_node classmethod not found in %s Node' % cls
|
||||||
|
|
||||||
|
|
||||||
class Node(BaseNode, Interface):
|
class Node(BaseNode, Interface):
|
||||||
pass
|
id = NodeIDField()
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
from py.test import raises
|
from py.test import raises
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
|
from graphene.relay.fields import (
|
||||||
|
NodeIDField
|
||||||
|
)
|
||||||
from graphene.core.fields import (
|
from graphene.core.fields import (
|
||||||
Field,
|
Field,
|
||||||
StringField,
|
StringField,
|
||||||
|
@ -56,6 +59,16 @@ def test_pseudo_interface():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_djangonode_idfield():
|
||||||
|
idfield = DjangoNode._meta.fields_map['id']
|
||||||
|
assert isinstance(idfield, NodeIDField)
|
||||||
|
|
||||||
|
|
||||||
|
def test_node_idfield():
|
||||||
|
idfield = Human._meta.fields_map['id']
|
||||||
|
assert isinstance(idfield, NodeIDField)
|
||||||
|
|
||||||
|
|
||||||
def test_interface_resolve_type():
|
def test_interface_resolve_type():
|
||||||
resolve_type = Character.resolve_type(schema, Human(object()))
|
resolve_type = Character.resolve_type(schema, Human(object()))
|
||||||
assert isinstance(resolve_type, GraphQLObjectType)
|
assert isinstance(resolve_type, GraphQLObjectType)
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
|
from graphql.core.type import (
|
||||||
|
GraphQLNonNull,
|
||||||
|
GraphQLID
|
||||||
|
)
|
||||||
|
|
||||||
import graphene
|
import graphene
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
|
@ -41,3 +45,9 @@ def test_nodefield_query():
|
||||||
result = schema.execute(query)
|
result = schema.execute(query)
|
||||||
assert not result.errors
|
assert not result.errors
|
||||||
assert result.data == expected
|
assert result.data == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_nodeidfield():
|
||||||
|
id_field = MyNode._meta.fields_map['id']
|
||||||
|
assert isinstance(id_field.internal_field(schema).type, GraphQLNonNull)
|
||||||
|
assert id_field.internal_field(schema).type.of_type == GraphQLID
|
||||||
|
|
Loading…
Reference in New Issue
Block a user