mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-30 13:33:55 +03:00
Fixed Graphene Django integration
This commit is contained in:
parent
043e548f49
commit
37ed617fce
|
@ -1,12 +1,12 @@
|
||||||
from cookbook.ingredients.models import Category, Ingredient
|
from cookbook.ingredients.models import Category, Ingredient
|
||||||
from graphene import ObjectType, relay
|
from graphene import ObjectType, relay
|
||||||
from graphene.contrib.django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
from graphene.contrib.django.types import DjangoNode
|
from graphene_django.types import DjangoNode, DjangoObjectType
|
||||||
|
|
||||||
|
|
||||||
# Graphene will automatically map the User model's fields onto the UserType.
|
# 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)
|
# This is configured in the UserType's Meta class (as you can see below)
|
||||||
class CategoryNode(DjangoNode):
|
class CategoryNode(DjangoNode, DjangoObjectType):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Category
|
model = Category
|
||||||
|
@ -14,7 +14,7 @@ class CategoryNode(DjangoNode):
|
||||||
filter_order_by = ['name']
|
filter_order_by = ['name']
|
||||||
|
|
||||||
|
|
||||||
class IngredientNode(DjangoNode):
|
class IngredientNode(DjangoNode, DjangoObjectType):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Ingredient
|
model = Ingredient
|
||||||
|
@ -34,6 +34,3 @@ class Query(ObjectType):
|
||||||
|
|
||||||
ingredient = relay.NodeField(IngredientNode)
|
ingredient = relay.NodeField(IngredientNode)
|
||||||
all_ingredients = DjangoFilterConnectionField(IngredientNode)
|
all_ingredients = DjangoFilterConnectionField(IngredientNode)
|
||||||
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
||||||
|
|
|
@ -5,5 +5,4 @@ import graphene
|
||||||
class Query(cookbook.ingredients.schema.Query):
|
class Query(cookbook.ingredients.schema.Query):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
schema = graphene.Schema(name='Cookbook Schema')
|
schema = graphene.Schema(name='Cookbook Schema', query=Query)
|
||||||
schema.query = Query
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import force_text
|
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.types.datetime import DateTime
|
||||||
from graphene.utils.str_converters import to_const
|
from graphene.utils.str_converters import to_const
|
||||||
from graphene.relay import Node, ConnectionField
|
from graphene.relay import Node, ConnectionField
|
||||||
|
@ -70,7 +71,7 @@ def convert_field_to_int(field, registry=None):
|
||||||
|
|
||||||
@convert_django_field.register(models.BooleanField)
|
@convert_django_field.register(models.BooleanField)
|
||||||
def convert_field_to_boolean(field, registry=None):
|
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)
|
@convert_django_field.register(models.NullBooleanField)
|
||||||
|
@ -130,6 +131,8 @@ def convert_field_to_djangomodel(field, registry=None):
|
||||||
@convert_django_field.register(ArrayField)
|
@convert_django_field.register(ArrayField)
|
||||||
def convert_postgres_array_to_list(field, registry=None):
|
def convert_postgres_array_to_list(field, registry=None):
|
||||||
base_type = convert_django_field(field.base_field)
|
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)
|
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)
|
@convert_django_field.register(RangeField)
|
||||||
def convert_posgres_range_to_string(field, registry=None):
|
def convert_posgres_range_to_string(field, registry=None):
|
||||||
inner_type = convert_django_field(field.base_field)
|
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)
|
return List(inner_type, description=field.help_text)
|
||||||
|
|
|
@ -6,6 +6,7 @@ from py.test import raises
|
||||||
import graphene
|
import graphene
|
||||||
from graphene.relay import Node, ConnectionField
|
from graphene.relay import Node, ConnectionField
|
||||||
from graphene.types.datetime import DateTime
|
from graphene.types.datetime import DateTime
|
||||||
|
from graphene.types.json import JSONString
|
||||||
from graphene.utils.get_graphql_type import get_graphql_type
|
from graphene.utils.get_graphql_type import get_graphql_type
|
||||||
# from graphene.core.types.custom_scalars import DateTime, JSONString
|
# 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():
|
def test_should_boolean_convert_boolean():
|
||||||
field = assert_conversion(models.BooleanField, graphene.Boolean)
|
field = assert_conversion(models.BooleanField, graphene.NonNull)
|
||||||
assert field.required is True
|
assert field.type.of_type == get_graphql_type(graphene.Boolean)
|
||||||
|
|
||||||
|
|
||||||
def test_should_nullboolean_convert_boolean():
|
def test_should_nullboolean_convert_boolean():
|
||||||
field = assert_conversion(models.NullBooleanField, graphene.Boolean)
|
assert_conversion(models.NullBooleanField, graphene.Boolean)
|
||||||
assert field.required is False
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_with_choices_convert_enum():
|
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():
|
def test_should_postgres_array_convert_list():
|
||||||
field = assert_conversion(ArrayField, graphene.List, models.CharField(max_length=100))
|
field = assert_conversion(ArrayField, graphene.List, models.CharField(max_length=100))
|
||||||
assert isinstance(field.type, graphene.List)
|
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,
|
@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)))
|
field = assert_conversion(ArrayField, graphene.List, ArrayField(models.CharField(max_length=100)))
|
||||||
assert isinstance(field.type, graphene.List)
|
assert isinstance(field.type, graphene.List)
|
||||||
assert isinstance(field.type.of_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,
|
@pytest.mark.skipif(HStoreField is MissingType,
|
||||||
|
@ -247,4 +247,5 @@ def test_should_postgres_json_convert_string():
|
||||||
def test_should_postgres_range_convert_list():
|
def test_should_postgres_range_convert_list():
|
||||||
from django.contrib.postgres.fields import IntegerRangeField
|
from django.contrib.postgres.fields import IntegerRangeField
|
||||||
field = assert_conversion(IntegerRangeField, graphene.List)
|
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)
|
||||||
|
|
|
@ -39,7 +39,8 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def __new__(cls, name, bases, attrs):
|
@staticmethod
|
||||||
|
def _create_objecttype(cls, name, bases, attrs):
|
||||||
# super_new = super(DjangoObjectTypeMeta, cls).__new__
|
# super_new = super(DjangoObjectTypeMeta, cls).__new__
|
||||||
super_new = type.__new__
|
super_new = type.__new__
|
||||||
|
|
||||||
|
@ -76,6 +77,7 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
|
||||||
fields=partial(cls._construct_fields, fields, options),
|
fields=partial(cls._construct_fields, fields, options),
|
||||||
interfaces=tuple(get_interfaces(interfaces + base_interfaces))
|
interfaces=tuple(get_interfaces(interfaces + base_interfaces))
|
||||||
)
|
)
|
||||||
|
options.get_fields = lambda: {}
|
||||||
|
|
||||||
if issubclass(cls, DjangoObjectType):
|
if issubclass(cls, DjangoObjectType):
|
||||||
options.registry.register(cls)
|
options.registry.register(cls)
|
||||||
|
@ -87,7 +89,7 @@ class DjangoObjectType(six.with_metaclass(DjangoObjectTypeMeta, ObjectType)):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class DjangoNodeMeta(NodeMeta, DjangoObjectTypeMeta):
|
class DjangoNodeMeta(DjangoObjectTypeMeta, NodeMeta):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_interface_options(meta):
|
def _get_interface_options(meta):
|
||||||
|
@ -99,8 +101,9 @@ class DjangoNodeMeta(NodeMeta, DjangoObjectTypeMeta):
|
||||||
registry=False
|
registry=False
|
||||||
)
|
)
|
||||||
|
|
||||||
def __new__(cls, name, bases, attrs):
|
@staticmethod
|
||||||
cls = super(DjangoNodeMeta, cls).__new__(cls, name, bases, attrs)
|
def _create_interface(cls, name, bases, attrs):
|
||||||
|
cls = super(DjangoNodeMeta, cls)._create_interface(cls, name, bases, attrs)
|
||||||
if not cls._meta.registry:
|
if not cls._meta.registry:
|
||||||
cls._meta.registry = get_global_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)
|
assert isinstance(cls._meta.registry, Registry), 'The attribute registry in {}.Meta needs to be an instance of Registry.'.format(name)
|
||||||
|
|
|
@ -38,7 +38,6 @@ class NodeMeta(ObjectTypeMeta):
|
||||||
def _create_interface(cls, name, bases, attrs):
|
def _create_interface(cls, name, bases, attrs):
|
||||||
options = cls._get_interface_options(attrs.pop('Meta', None))
|
options = cls._get_interface_options(attrs.pop('Meta', None))
|
||||||
cls = type.__new__(cls, name, bases, dict(attrs, _meta=options))
|
cls = type.__new__(cls, name, bases, dict(attrs, _meta=options))
|
||||||
|
|
||||||
get_node_from_global_id = getattr(cls, 'get_node_from_global_id', None)
|
get_node_from_global_id = getattr(cls, 'get_node_from_global_id', None)
|
||||||
id_resolver = getattr(cls, 'id_resolver', 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__)
|
assert get_node_from_global_id, '{}.get_node_from_global_id method is required by the Node interface.'.format(cls.__name__)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user