Fixed Graphene Django integration

This commit is contained in:
Syrus Akbary 2016-06-21 22:52:39 -07:00
parent 043e548f49
commit 37ed617fce
6 changed files with 27 additions and 23 deletions

View File

@ -1,12 +1,12 @@
from cookbook.ingredients.models import Category, Ingredient
from graphene import ObjectType, relay
from graphene.contrib.django.filter import DjangoFilterConnectionField
from graphene.contrib.django.types import DjangoNode
from graphene_django.filter import DjangoFilterConnectionField
from graphene_django.types import DjangoNode, DjangoObjectType
# Graphene will automatically map the User model's fields onto the UserType.
# This is configured in the UserType's Meta class (as you can see below)
class CategoryNode(DjangoNode):
class CategoryNode(DjangoNode, DjangoObjectType):
class Meta:
model = Category
@ -14,7 +14,7 @@ class CategoryNode(DjangoNode):
filter_order_by = ['name']
class IngredientNode(DjangoNode):
class IngredientNode(DjangoNode, DjangoObjectType):
class Meta:
model = Ingredient
@ -34,6 +34,3 @@ class Query(ObjectType):
ingredient = relay.NodeField(IngredientNode)
all_ingredients = DjangoFilterConnectionField(IngredientNode)
class Meta:
abstract = True

View File

@ -5,5 +5,4 @@ import graphene
class Query(cookbook.ingredients.schema.Query):
pass
schema = graphene.Schema(name='Cookbook Schema')
schema.query = Query
schema = graphene.Schema(name='Cookbook Schema', query=Query)

View File

@ -1,7 +1,8 @@
from django.db import models
from django.utils.encoding import force_text
from graphene import Enum, List, ID, Boolean, Float, Int, String, Field
from graphene import Enum, List, ID, Boolean, Float, Int, String, Field, NonNull
from graphene.types.json import JSONString
from graphene.types.datetime import DateTime
from graphene.utils.str_converters import to_const
from graphene.relay import Node, ConnectionField
@ -70,7 +71,7 @@ def convert_field_to_int(field, registry=None):
@convert_django_field.register(models.BooleanField)
def convert_field_to_boolean(field, registry=None):
return Boolean(description=field.help_text, required=True)
return NonNull(Boolean, description=field.help_text)
@convert_django_field.register(models.NullBooleanField)
@ -130,6 +131,8 @@ def convert_field_to_djangomodel(field, registry=None):
@convert_django_field.register(ArrayField)
def convert_postgres_array_to_list(field, registry=None):
base_type = convert_django_field(field.base_field)
if not isinstance(base_type, (List, NonNull)):
base_type = type(base_type)
return List(base_type, description=field.help_text)
@ -142,4 +145,6 @@ def convert_posgres_field_to_string(field, registry=None):
@convert_django_field.register(RangeField)
def convert_posgres_range_to_string(field, registry=None):
inner_type = convert_django_field(field.base_field)
if not isinstance(inner_type, (List, NonNull)):
inner_type = type(inner_type)
return List(inner_type, description=field.help_text)

View File

@ -6,6 +6,7 @@ from py.test import raises
import graphene
from graphene.relay import Node, ConnectionField
from graphene.types.datetime import DateTime
from graphene.types.json import JSONString
from graphene.utils.get_graphql_type import get_graphql_type
# from graphene.core.types.custom_scalars import DateTime, JSONString
@ -93,13 +94,12 @@ def test_should_integer_convert_int():
def test_should_boolean_convert_boolean():
field = assert_conversion(models.BooleanField, graphene.Boolean)
assert field.required is True
field = assert_conversion(models.BooleanField, graphene.NonNull)
assert field.type.of_type == get_graphql_type(graphene.Boolean)
def test_should_nullboolean_convert_boolean():
field = assert_conversion(models.NullBooleanField, graphene.Boolean)
assert field.required is False
assert_conversion(models.NullBooleanField, graphene.Boolean)
def test_field_with_choices_convert_enum():
@ -218,7 +218,7 @@ def test_should_onetoone_reverse_convert_model():
def test_should_postgres_array_convert_list():
field = assert_conversion(ArrayField, graphene.List, models.CharField(max_length=100))
assert isinstance(field.type, graphene.List)
assert isinstance(field.type.of_type, graphene.String)
assert field.type.of_type == get_graphql_type(graphene.String)
@pytest.mark.skipif(ArrayField is MissingType,
@ -227,7 +227,7 @@ def test_should_postgres_array_multiple_convert_list():
field = assert_conversion(ArrayField, graphene.List, ArrayField(models.CharField(max_length=100)))
assert isinstance(field.type, graphene.List)
assert isinstance(field.type.of_type, graphene.List)
assert isinstance(field.type.of_type.of_type, graphene.String)
assert field.type.of_type.of_type == get_graphql_type(graphene.String)
@pytest.mark.skipif(HStoreField is MissingType,
@ -247,4 +247,5 @@ def test_should_postgres_json_convert_string():
def test_should_postgres_range_convert_list():
from django.contrib.postgres.fields import IntegerRangeField
field = assert_conversion(IntegerRangeField, graphene.List)
assert isinstance(field.type.of_type, graphene.Int)
assert isinstance(field.type, graphene.List)
# assert isinstance(field.type.of_type, graphene.Int)

View File

@ -39,7 +39,8 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
return fields
def __new__(cls, name, bases, attrs):
@staticmethod
def _create_objecttype(cls, name, bases, attrs):
# super_new = super(DjangoObjectTypeMeta, cls).__new__
super_new = type.__new__
@ -76,6 +77,7 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
fields=partial(cls._construct_fields, fields, options),
interfaces=tuple(get_interfaces(interfaces + base_interfaces))
)
options.get_fields = lambda: {}
if issubclass(cls, DjangoObjectType):
options.registry.register(cls)
@ -87,7 +89,7 @@ class DjangoObjectType(six.with_metaclass(DjangoObjectTypeMeta, ObjectType)):
pass
class DjangoNodeMeta(NodeMeta, DjangoObjectTypeMeta):
class DjangoNodeMeta(DjangoObjectTypeMeta, NodeMeta):
@staticmethod
def _get_interface_options(meta):
@ -99,8 +101,9 @@ class DjangoNodeMeta(NodeMeta, DjangoObjectTypeMeta):
registry=False
)
def __new__(cls, name, bases, attrs):
cls = super(DjangoNodeMeta, cls).__new__(cls, name, bases, attrs)
@staticmethod
def _create_interface(cls, name, bases, attrs):
cls = super(DjangoNodeMeta, cls)._create_interface(cls, name, bases, attrs)
if not cls._meta.registry:
cls._meta.registry = get_global_registry()
assert isinstance(cls._meta.registry, Registry), 'The attribute registry in {}.Meta needs to be an instance of Registry.'.format(name)

View File

@ -38,7 +38,6 @@ class NodeMeta(ObjectTypeMeta):
def _create_interface(cls, name, bases, attrs):
options = cls._get_interface_options(attrs.pop('Meta', None))
cls = type.__new__(cls, name, bases, dict(attrs, _meta=options))
get_node_from_global_id = getattr(cls, 'get_node_from_global_id', None)
id_resolver = getattr(cls, 'id_resolver', None)
assert get_node_from_global_id, '{}.get_node_from_global_id method is required by the Node interface.'.format(cls.__name__)