mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-11 04:07:16 +03:00
Improved Django model conversion
This commit is contained in:
parent
2e8707aee6
commit
76147d7c26
|
@ -7,34 +7,48 @@ from graphene.core.fields import (
|
|||
IntField,
|
||||
BooleanField,
|
||||
FloatField,
|
||||
ListField
|
||||
)
|
||||
from graphene.contrib.django.fields import DjangoModelField
|
||||
|
||||
@singledispatch
|
||||
def convert_django_field(field):
|
||||
raise Exception("Don't know how to convert the Django field %s"%field)
|
||||
def convert_django_field(field, cls):
|
||||
raise Exception("Don't know how to convert the Django field %s (%s)" % (field, field.__class__))
|
||||
|
||||
|
||||
@convert_django_field.register(models.DateField)
|
||||
@convert_django_field.register(models.CharField)
|
||||
def _(field):
|
||||
@convert_django_field.register(models.TextField)
|
||||
def _(field, cls):
|
||||
return StringField(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.AutoField)
|
||||
def _(field):
|
||||
def _(field, cls):
|
||||
return IDField(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.BigIntegerField)
|
||||
@convert_django_field.register(models.IntegerField)
|
||||
def _(field):
|
||||
def _(field, cls):
|
||||
return IntField(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.BooleanField)
|
||||
def _(field):
|
||||
def _(field, cls):
|
||||
return BooleanField(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.FloatField)
|
||||
def _(field):
|
||||
def _(field, cls):
|
||||
return FloatField(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.ManyToOneRel)
|
||||
def _(field, cls):
|
||||
return ListField(DjangoModelField(field.related_model))
|
||||
|
||||
|
||||
@convert_django_field.register(models.ForeignKey)
|
||||
def _(field, cls):
|
||||
return DjangoModelField(field.related_model)
|
||||
|
|
23
graphene/contrib/django/fields.py
Normal file
23
graphene/contrib/django/fields.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from graphene.core.fields import Field
|
||||
from graphene.utils import cached_property
|
||||
|
||||
from graphene.env import get_global_schema
|
||||
|
||||
|
||||
def get_type_for_model(schema, model):
|
||||
schema = schema or get_global_schema()
|
||||
types = schema.types.values()
|
||||
for _type in types:
|
||||
type_model = getattr(_type._meta, 'model', None)
|
||||
if model == type_model:
|
||||
return _type._meta.type
|
||||
|
||||
|
||||
class DjangoModelField(Field):
|
||||
def __init__(self, model):
|
||||
super(DjangoModelField, self).__init__(None)
|
||||
self.model = model
|
||||
|
||||
@cached_property
|
||||
def type(self):
|
||||
return get_type_for_model(self.schema, self.model)
|
|
@ -1,4 +1,5 @@
|
|||
import six
|
||||
from django.db import models
|
||||
|
||||
from graphene.core.types import ObjectTypeMeta, ObjectType
|
||||
from graphene.contrib.django.options import DjangoOptions
|
||||
|
@ -6,6 +7,13 @@ from graphene.contrib.django.converter import convert_django_field
|
|||
|
||||
from graphene.relay import Node
|
||||
|
||||
def get_reverse_fields(model):
|
||||
for name, attr in model.__dict__.items():
|
||||
related = getattr(attr, 'related', None)
|
||||
if isinstance(related, models.ManyToOneRel):
|
||||
yield related
|
||||
|
||||
|
||||
class DjangoObjectTypeMeta(ObjectTypeMeta):
|
||||
options_cls = DjangoOptions
|
||||
def add_extra_fields(cls):
|
||||
|
@ -14,10 +22,11 @@ class DjangoObjectTypeMeta(ObjectTypeMeta):
|
|||
|
||||
only_fields = cls._meta.only_fields
|
||||
# print cls._meta.model._meta._get_fields(forward=False, reverse=True, include_hidden=True)
|
||||
for field in cls._meta.model._meta.fields:
|
||||
reverse_fields = tuple(get_reverse_fields(cls._meta.model))
|
||||
for field in cls._meta.model._meta.fields + reverse_fields:
|
||||
if only_fields and field.name not in only_fields:
|
||||
continue
|
||||
converted_field = convert_django_field(field)
|
||||
converted_field = convert_django_field(field, cls)
|
||||
cls.add_to_class(field.name, converted_field)
|
||||
|
||||
|
||||
|
|
|
@ -76,8 +76,8 @@ class Field(object):
|
|||
|
||||
@cached_property
|
||||
def field(self):
|
||||
if not self.field_type:
|
||||
raise Exception('Must specify a field GraphQL type for the field %s'%self.field_name)
|
||||
# if not self.field_type:
|
||||
# raise Exception('Must specify a field GraphQL type for the field %s'%self.field_name)
|
||||
|
||||
if not self.object_type:
|
||||
raise Exception('Field could not be constructed in a non graphene.Type or graphene.Interface')
|
||||
|
|
|
@ -16,6 +16,14 @@ class Options(object):
|
|||
self.parents = []
|
||||
self.valid_attrs = DEFAULT_NAMES
|
||||
|
||||
# @property
|
||||
# def schema(self):
|
||||
# return self._schema or get_global_schema()
|
||||
|
||||
# @schema.setter
|
||||
# def schema(self, schema):
|
||||
# self._schema = schema
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
cls._meta = self
|
||||
self.parent = cls
|
||||
|
|
|
@ -42,6 +42,10 @@ class Schema(object):
|
|||
raise Exception('Type %s not found in %r' % (type_name, self))
|
||||
return self._types[type_name]
|
||||
|
||||
@property
|
||||
def types(self):
|
||||
return self._types
|
||||
|
||||
def execute(self, request='', root=None, vars=None, operation_name=None):
|
||||
root = root or object()
|
||||
return graphql(
|
||||
|
|
|
@ -74,6 +74,14 @@ def test_should_node():
|
|||
def get_node(cls, id):
|
||||
return ReporterNodeType(Reporter(id=2, first_name='Cookie Monster'))
|
||||
|
||||
class ArticleNodeType(DjangoNode):
|
||||
class Meta:
|
||||
model = Article
|
||||
|
||||
@classmethod
|
||||
def get_node(cls, id):
|
||||
return ArticleNodeType(None)
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
node = relay.NodeField()
|
||||
reporter = graphene.Field(ReporterNodeType)
|
||||
|
|
Loading…
Reference in New Issue
Block a user