Improved django support

This commit is contained in:
Syrus Akbary 2015-11-11 17:33:37 -08:00
parent b0f2b4dd55
commit cf657b365c
4 changed files with 50 additions and 56 deletions

View File

@ -5,6 +5,7 @@ from graphene.contrib.django.fields import (ConnectionOrListField,
DjangoModelField) DjangoModelField)
from graphene.core.fields import (BooleanField, FloatField, IDField, IntField, from graphene.core.fields import (BooleanField, FloatField, IDField, IntField,
StringField) StringField)
from graphene.core.types.scalars import Boolean, Float, ID, Int, String
try: try:
UUIDField = models.UUIDField UUIDField = models.UUIDField
@ -28,12 +29,12 @@ def convert_django_field(field):
@convert_django_field.register(models.URLField) @convert_django_field.register(models.URLField)
@convert_django_field.register(UUIDField) @convert_django_field.register(UUIDField)
def convert_field_to_string(field): def convert_field_to_string(field):
return StringField(description=field.help_text) return String(description=field.help_text)
@convert_django_field.register(models.AutoField) @convert_django_field.register(models.AutoField)
def convert_field_to_id(field): def convert_field_to_id(field):
return IDField(description=field.help_text) return ID(description=field.help_text)
@convert_django_field.register(models.PositiveIntegerField) @convert_django_field.register(models.PositiveIntegerField)
@ -42,23 +43,23 @@ def convert_field_to_id(field):
@convert_django_field.register(models.BigIntegerField) @convert_django_field.register(models.BigIntegerField)
@convert_django_field.register(models.IntegerField) @convert_django_field.register(models.IntegerField)
def convert_field_to_int(field): def convert_field_to_int(field):
return IntField(description=field.help_text) return Int(description=field.help_text)
@convert_django_field.register(models.BooleanField) @convert_django_field.register(models.BooleanField)
def convert_field_to_boolean(field): def convert_field_to_boolean(field):
return BooleanField(description=field.help_text, required=True) return Boolean(description=field.help_text, required=True)
@convert_django_field.register(models.NullBooleanField) @convert_django_field.register(models.NullBooleanField)
def convert_field_to_nullboolean(field): def convert_field_to_nullboolean(field):
return BooleanField(description=field.help_text) return Boolean(description=field.help_text)
@convert_django_field.register(models.DecimalField) @convert_django_field.register(models.DecimalField)
@convert_django_field.register(models.FloatField) @convert_django_field.register(models.FloatField)
def convert_field_to_float(field): def convert_field_to_float(field):
return FloatField(description=field.help_text) return Float(description=field.help_text)
@convert_django_field.register(models.ManyToManyField) @convert_django_field.register(models.ManyToManyField)

View File

@ -1,6 +1,7 @@
from graphene import relay from graphene import relay
from graphene.contrib.django.utils import get_type_for_model, lazy_map from graphene.contrib.django.utils import get_type_for_model, lazy_map
from graphene.core.fields import Field, LazyField, ListField from graphene.core.fields import Field, ListField
from graphene.core.types.base import FieldType
from graphene.relay.utils import is_node from graphene.relay.utils import is_node
@ -8,60 +9,49 @@ class DjangoConnectionField(relay.ConnectionField):
def wrap_resolved(self, value, instance, args, info): def wrap_resolved(self, value, instance, args, info):
schema = info.schema.graphene_schema schema = info.schema.graphene_schema
return lazy_map(value, self.get_object_type(schema)) return lazy_map(value, self.type.get_object_type(schema))
class LazyListField(ListField): class LazyListField(ListField):
def resolve(self, instance, args, info): def resolver(self, instance, args, info):
schema = info.schema.graphene_schema schema = info.schema.graphene_schema
resolved = super(LazyListField, self).resolve(instance, args, info) resolved = super(LazyListField, self).resolver(instance, args, info)
return lazy_map(resolved, self.get_object_type(schema)) return lazy_map(resolved, self.get_object_type(schema))
class ConnectionOrListField(LazyField): class ConnectionOrListField(Field):
def get_field(self, schema): def internal_type(self, schema):
model_field = self.field_type model_field = self.type
field_object_type = model_field.get_object_type(schema) field_object_type = model_field.get_object_type(schema)
if is_node(field_object_type): if is_node(field_object_type):
field = DjangoConnectionField(model_field) field = DjangoConnectionField(model_field)
else: else:
field = LazyListField(model_field) field = LazyListField(model_field)
field.contribute_to_class(self.object_type, self.name) field.contribute_to_class(self.object_type, self.name)
return field return field.internal_type(schema)
class DjangoModelField(Field): class DjangoModelField(FieldType):
def __init__(self, model, *args, **kwargs): def __init__(self, model, *args, **kwargs):
super(DjangoModelField, self).__init__(None, *args, **kwargs)
self.model = model self.model = model
super(DjangoModelField, self).__init__(*args, **kwargs)
def resolve(self, instance, args, info):
resolved = super(DjangoModelField, self).resolve(instance, args, info)
schema = info.schema.graphene_schema
_type = self.get_object_type(schema)
assert _type, ("Field %s cannot be retrieved as the "
"ObjectType is not registered by the schema" % (
self.attname
))
return _type(resolved)
def internal_type(self, schema): def internal_type(self, schema):
_type = self.get_object_type(schema) _type = self.get_object_type(schema)
if not _type and self.object_type._meta.only_fields: if not _type and self.parent._meta.only_fields:
raise Exception( raise Exception(
"Model %r is not accessible by the schema. " "Model %r is not accessible by the schema. "
"You can either register the type manually " "You can either register the type manually "
"using @schema.register. " "using @schema.register. "
"Or disable the field %s in %s" % ( "Or disable the field in %s" % (
self.model, self.model,
self.attname, self.parent,
self.object_type
) )
) )
return schema.T(_type) or Field.SKIP return schema.T(_type)
def get_object_type(self, schema): def get_object_type(self, schema):
return get_type_for_model(schema, self.model) return get_type_for_model(schema, self.model)

View File

@ -15,8 +15,9 @@ def assert_conversion(django_field, graphene_field, *args):
field = django_field(*args, help_text='Custom Help Text') field = django_field(*args, help_text='Custom Help Text')
graphene_type = convert_django_field(field) graphene_type = convert_django_field(field)
assert isinstance(graphene_type, graphene_field) assert isinstance(graphene_type, graphene_field)
assert graphene_type.description == 'Custom Help Text' field = graphene_type.as_field()
return graphene_type assert field.description == 'Custom Help Text'
return field
def test_should_unknown_django_field_raise_exception(): def test_should_unknown_django_field_raise_exception():
@ -26,86 +27,86 @@ def test_should_unknown_django_field_raise_exception():
def test_should_date_convert_string(): def test_should_date_convert_string():
assert_conversion(models.DateField, graphene.StringField) assert_conversion(models.DateField, graphene.String)
def test_should_char_convert_string(): def test_should_char_convert_string():
assert_conversion(models.CharField, graphene.StringField) assert_conversion(models.CharField, graphene.String)
def test_should_text_convert_string(): def test_should_text_convert_string():
assert_conversion(models.TextField, graphene.StringField) assert_conversion(models.TextField, graphene.String)
def test_should_email_convert_string(): def test_should_email_convert_string():
assert_conversion(models.EmailField, graphene.StringField) assert_conversion(models.EmailField, graphene.String)
def test_should_slug_convert_string(): def test_should_slug_convert_string():
assert_conversion(models.SlugField, graphene.StringField) assert_conversion(models.SlugField, graphene.String)
def test_should_url_convert_string(): def test_should_url_convert_string():
assert_conversion(models.URLField, graphene.StringField) assert_conversion(models.URLField, graphene.String)
def test_should_auto_convert_id(): def test_should_auto_convert_id():
assert_conversion(models.AutoField, graphene.IDField) assert_conversion(models.AutoField, graphene.ID)
def test_should_positive_integer_convert_int(): def test_should_positive_integer_convert_int():
assert_conversion(models.PositiveIntegerField, graphene.IntField) assert_conversion(models.PositiveIntegerField, graphene.Int)
def test_should_positive_small_convert_int(): def test_should_positive_small_convert_int():
assert_conversion(models.PositiveSmallIntegerField, graphene.IntField) assert_conversion(models.PositiveSmallIntegerField, graphene.Int)
def test_should_small_integer_convert_int(): def test_should_small_integer_convert_int():
assert_conversion(models.SmallIntegerField, graphene.IntField) assert_conversion(models.SmallIntegerField, graphene.Int)
def test_should_big_integer_convert_int(): def test_should_big_integer_convert_int():
assert_conversion(models.BigIntegerField, graphene.IntField) assert_conversion(models.BigIntegerField, graphene.Int)
def test_should_integer_convert_int(): def test_should_integer_convert_int():
assert_conversion(models.IntegerField, graphene.IntField) assert_conversion(models.IntegerField, graphene.Int)
def test_should_boolean_convert_boolean(): def test_should_boolean_convert_boolean():
field = assert_conversion(models.BooleanField, graphene.BooleanField) field = assert_conversion(models.BooleanField, graphene.Boolean)
assert field.required is True assert field.required is True
def test_should_nullboolean_convert_boolean(): def test_should_nullboolean_convert_boolean():
field = assert_conversion(models.NullBooleanField, graphene.BooleanField) field = assert_conversion(models.NullBooleanField, graphene.Boolean)
assert field.required is False assert field.required is False
def test_should_float_convert_float(): def test_should_float_convert_float():
assert_conversion(models.FloatField, graphene.FloatField) assert_conversion(models.FloatField, graphene.Float)
def test_should_manytomany_convert_connectionorlist(): def test_should_manytomany_convert_connectionorlist():
graphene_type = convert_django_field(Reporter._meta.local_many_to_many[0]) graphene_type = convert_django_field(Reporter._meta.local_many_to_many[0])
assert isinstance(graphene_type, ConnectionOrListField) assert isinstance(graphene_type, ConnectionOrListField)
assert isinstance(graphene_type.field_type, DjangoModelField) assert isinstance(graphene_type.type, DjangoModelField)
assert graphene_type.field_type.model == Reporter assert graphene_type.type.model == Reporter
def test_should_manytoone_convert_connectionorlist(): def test_should_manytoone_convert_connectionorlist():
graphene_type = convert_django_field(Reporter.articles.related) graphene_type = convert_django_field(Reporter.articles.related)
assert isinstance(graphene_type, ConnectionOrListField) assert isinstance(graphene_type, ConnectionOrListField)
assert isinstance(graphene_type.field_type, DjangoModelField) assert isinstance(graphene_type.type, DjangoModelField)
assert graphene_type.field_type.model == Article assert graphene_type.type.model == Article
def test_should_onetoone_convert_model(): def test_should_onetoone_convert_model():
field = assert_conversion(models.OneToOneField, DjangoModelField, Article) field = assert_conversion(models.OneToOneField, DjangoModelField, Article)
assert field.model == Article assert field.type.model == Article
def test_should_foreignkey_convert_model(): def test_should_foreignkey_convert_model():
field = assert_conversion(models.ForeignKey, DjangoModelField, Article) field = assert_conversion(models.ForeignKey, DjangoModelField, Article)
assert field.model == Article assert field.type.model == Article

View File

@ -2,7 +2,8 @@
from graphene import Schema from graphene import Schema
from graphene.contrib.django.types import DjangoInterface, DjangoNode from graphene.contrib.django.types import DjangoInterface, DjangoNode
from graphene.core.fields import IntField from graphene.core.fields import IntField, Field
from graphene.core.types.scalars import String, Int
from graphene.relay.fields import GlobalIDField from graphene.relay.fields import GlobalIDField
from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType
from tests.utils import assert_equal_lists from tests.utils import assert_equal_lists
@ -57,7 +58,8 @@ def test_node_idfield():
def test_node_replacedfield(): def test_node_replacedfield():
idfield = Human._meta.fields_map['pub_date'] idfield = Human._meta.fields_map['pub_date']
assert isinstance(idfield, IntField) assert isinstance(idfield, Field)
assert schema.T(idfield).type == schema.T(Int())
def test_interface_resolve_type(): def test_interface_resolve_type():