mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-26 19:43:56 +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 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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__)
|
||||
|
|
Loading…
Reference in New Issue
Block a user