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.utils.str_converters import to_const from graphene.relay import Node, ConnectionField # from ...core.types.custom_scalars import DateTime, JSONString from .compat import (ArrayField, HStoreField, JSONField, RangeField, RelatedObject, UUIDField) from .utils import get_related_model, import_single_dispatch from .fields import DjangoConnectionField singledispatch = import_single_dispatch() class Registry(object): def __init__(self): self._registry = {} self._registry_models = {} def register(self, cls): from .types import DjangoObjectType print(cls.get_registry(), self) assert issubclass(cls, DjangoObjectType), 'Only DjangoObjectTypes can be registered, received "{}"'.format(cls.__name__) assert cls.get_registry() == self, 'Registry for a Model have to match.' self._registry[cls._meta.model] = cls def get_type_for_model(self, model): return self._registry.get(model) def convert_choices(choices): for value, name in choices: if isinstance(name, (tuple, list)): for choice in convert_choices(name): yield choice else: yield to_const(force_text(name)), value def convert_django_field_with_choices(field, registry=None): choices = getattr(field, 'choices', None) if choices: meta = field.model._meta name = '{}_{}_{}'.format(meta.app_label, meta.object_name, field.name) graphql_choices = list(convert_choices(choices)) return Enum(name.upper(), graphql_choices, description=field.help_text) return convert_django_field(field, registry) @singledispatch def convert_django_field(field, registry=None): raise Exception( "Don't know how to convert the Django field %s (%s)" % (field, field.__class__)) @convert_django_field.register(models.CharField) @convert_django_field.register(models.TextField) @convert_django_field.register(models.EmailField) @convert_django_field.register(models.SlugField) @convert_django_field.register(models.URLField) @convert_django_field.register(models.GenericIPAddressField) @convert_django_field.register(models.FileField) @convert_django_field.register(UUIDField) def convert_field_to_string(field, registry=None): return String(description=field.help_text) @convert_django_field.register(models.AutoField) def convert_field_to_id(field, registry=None): return ID(description=field.help_text) @convert_django_field.register(models.PositiveIntegerField) @convert_django_field.register(models.PositiveSmallIntegerField) @convert_django_field.register(models.SmallIntegerField) @convert_django_field.register(models.BigIntegerField) @convert_django_field.register(models.IntegerField) def convert_field_to_int(field, registry=None): return Int(description=field.help_text) @convert_django_field.register(models.BooleanField) def convert_field_to_boolean(field, registry=None): return Boolean(description=field.help_text, required=True) @convert_django_field.register(models.NullBooleanField) def convert_field_to_nullboolean(field, registry=None): return Boolean(description=field.help_text) @convert_django_field.register(models.DecimalField) @convert_django_field.register(models.FloatField) def convert_field_to_float(field, registry=None): return Float(description=field.help_text) @convert_django_field.register(models.DateField) def convert_date_to_string(field, registry=None): return DateTime(description=field.help_text) @convert_django_field.register(models.OneToOneRel) def convert_onetoone_field_to_djangomodel(field, registry=None): model = get_related_model(field) return Field(registry.get_type_for_model(model)) @convert_django_field.register(models.ManyToManyField) @convert_django_field.register(models.ManyToManyRel) @convert_django_field.register(models.ManyToOneRel) def convert_field_to_list_or_connection(field, registry=None): model = get_related_model(field) _type = registry.get_type_for_model(model) if not _type: return if issubclass(_type, Node): return DjangoConnectionField(_type) return Field(List(_type)) # For Django 1.6 @convert_django_field.register(RelatedObject) def convert_relatedfield_to_djangomodel(field, registry=None): model = field.model _type = registry.get_type_for_model(model) if issubclass(_type, Node): return DjangoConnectionField(_type) return Field(List(_type)) @convert_django_field.register(models.OneToOneField) @convert_django_field.register(models.ForeignKey) def convert_field_to_djangomodel(field, registry=None): model = get_related_model(field) _type = registry.get_type_for_model(model) return Field(_type, description=field.help_text) @convert_django_field.register(ArrayField) def convert_postgres_array_to_list(field, registry=None): base_type = convert_django_field(field.base_field) return List(base_type, description=field.help_text) @convert_django_field.register(HStoreField) @convert_django_field.register(JSONField) def convert_posgres_field_to_string(field, registry=None): return JSONString(description=field.help_text) @convert_django_field.register(RangeField) def convert_posgres_range_to_string(field, registry=None): inner_type = convert_django_field(field.base_field) return List(inner_type, description=field.help_text)