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)
from graphene.core.fields import (BooleanField, FloatField, IDField, IntField,
StringField)
from graphene.core.types.scalars import Boolean, Float, ID, Int, String
try:
UUIDField = models.UUIDField
@ -28,12 +29,12 @@ def convert_django_field(field):
@convert_django_field.register(models.URLField)
@convert_django_field.register(UUIDField)
def convert_field_to_string(field):
return StringField(description=field.help_text)
return String(description=field.help_text)
@convert_django_field.register(models.AutoField)
def convert_field_to_id(field):
return IDField(description=field.help_text)
return ID(description=field.help_text)
@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.IntegerField)
def convert_field_to_int(field):
return IntField(description=field.help_text)
return Int(description=field.help_text)
@convert_django_field.register(models.BooleanField)
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)
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.FloatField)
def convert_field_to_float(field):
return FloatField(description=field.help_text)
return Float(description=field.help_text)
@convert_django_field.register(models.ManyToManyField)

View File

@ -1,6 +1,7 @@
from graphene import relay
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
@ -8,60 +9,49 @@ class DjangoConnectionField(relay.ConnectionField):
def wrap_resolved(self, value, instance, args, info):
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):
def resolve(self, instance, args, info):
def resolver(self, instance, args, info):
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))
class ConnectionOrListField(LazyField):
class ConnectionOrListField(Field):
def get_field(self, schema):
model_field = self.field_type
def internal_type(self, schema):
model_field = self.type
field_object_type = model_field.get_object_type(schema)
if is_node(field_object_type):
field = DjangoConnectionField(model_field)
else:
field = LazyListField(model_field)
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):
super(DjangoModelField, self).__init__(None, *args, **kwargs)
self.model = model
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)
super(DjangoModelField, self).__init__(*args, **kwargs)
def internal_type(self, 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(
"Model %r is not accessible by the schema. "
"You can either register the type manually "
"using @schema.register. "
"Or disable the field %s in %s" % (
"Or disable the field in %s" % (
self.model,
self.attname,
self.object_type
self.parent,
)
)
return schema.T(_type) or Field.SKIP
return schema.T(_type)
def get_object_type(self, schema):
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')
graphene_type = convert_django_field(field)
assert isinstance(graphene_type, graphene_field)
assert graphene_type.description == 'Custom Help Text'
return graphene_type
field = graphene_type.as_field()
assert field.description == 'Custom Help Text'
return field
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():
assert_conversion(models.DateField, graphene.StringField)
assert_conversion(models.DateField, graphene.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():
assert_conversion(models.TextField, graphene.StringField)
assert_conversion(models.TextField, graphene.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():
assert_conversion(models.SlugField, graphene.StringField)
assert_conversion(models.SlugField, graphene.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():
assert_conversion(models.AutoField, graphene.IDField)
assert_conversion(models.AutoField, graphene.ID)
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():
assert_conversion(models.PositiveSmallIntegerField, graphene.IntField)
assert_conversion(models.PositiveSmallIntegerField, graphene.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():
assert_conversion(models.BigIntegerField, graphene.IntField)
assert_conversion(models.BigIntegerField, graphene.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():
field = assert_conversion(models.BooleanField, graphene.BooleanField)
field = assert_conversion(models.BooleanField, graphene.Boolean)
assert field.required is True
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
def test_should_float_convert_float():
assert_conversion(models.FloatField, graphene.FloatField)
assert_conversion(models.FloatField, graphene.Float)
def test_should_manytomany_convert_connectionorlist():
graphene_type = convert_django_field(Reporter._meta.local_many_to_many[0])
assert isinstance(graphene_type, ConnectionOrListField)
assert isinstance(graphene_type.field_type, DjangoModelField)
assert graphene_type.field_type.model == Reporter
assert isinstance(graphene_type.type, DjangoModelField)
assert graphene_type.type.model == Reporter
def test_should_manytoone_convert_connectionorlist():
graphene_type = convert_django_field(Reporter.articles.related)
assert isinstance(graphene_type, ConnectionOrListField)
assert isinstance(graphene_type.field_type, DjangoModelField)
assert graphene_type.field_type.model == Article
assert isinstance(graphene_type.type, DjangoModelField)
assert graphene_type.type.model == Article
def test_should_onetoone_convert_model():
field = assert_conversion(models.OneToOneField, DjangoModelField, Article)
assert field.model == Article
assert field.type.model == Article
def test_should_foreignkey_convert_model():
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.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 graphql.core.type import GraphQLInterfaceType, GraphQLObjectType
from tests.utils import assert_equal_lists
@ -57,7 +58,8 @@ def test_node_idfield():
def test_node_replacedfield():
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():