graphene-django/graphene_django/converter.py
Mardanov Timur Rustemovich 54fa1ee876 nonnull fields deleted
2019-02-05 12:52:19 +03:00

210 lines
6.0 KiB
Python

from django.db import models
from django.utils.encoding import force_text
from neomodel import (
AliasProperty,
ArrayProperty,
BooleanProperty,
DateProperty,
DateTimeProperty,
EmailProperty,
FloatProperty,
IntegerProperty,
JSONProperty,
RegexProperty,
StringProperty,
UniqueIdProperty,
ZeroOrMore,
ZeroOrOne,
One,
OneOrMore,
)
from neomodel.relationship_manager import RelationshipDefinition
try:
# TimurMardanov fork branch. Supports contain 2D-xD arrays
from neomodel import JsonArrayProperty # noqa
jsonArrayProperty = JsonArrayProperty
except BaseException:
jsonArrayProperty = JSONProperty
from graphene import (
ID,
Boolean,
Dynamic,
Enum,
Field,
Float,
Int,
List,
NonNull,
String,
UUID,
DateTime,
Date,
Time,
)
from graphene.types.json import JSONString
from graphene.utils.str_converters import to_camel_case, to_const
from graphql import assert_valid_name
from .compat import ArrayField, HStoreField, JSONField, RangeField
from .fields import DjangoListField, DjangoConnectionField
from .utils import import_single_dispatch
singledispatch = import_single_dispatch()
REQUIRED_CARDINALITY = (One, OneOrMore, )
NOT_REQUIRED_CARDINALITY = (ZeroOrMore, ZeroOrOne,)
@singledispatch
def define_null_parameter(manager):
raise Exception(
"Don't know how to convert the Neomodel relationship field"
)
@define_null_parameter.register(REQUIRED_CARDINALITY[0])
@define_null_parameter.register(REQUIRED_CARDINALITY[1])
def return_required(field):
return True
@define_null_parameter.register(NOT_REQUIRED_CARDINALITY[0])
@define_null_parameter.register(NOT_REQUIRED_CARDINALITY[1])
def return_required(field):
return False
def convert_choice_name(name):
name = to_const(force_text(name))
try:
assert_valid_name(name)
except AssertionError:
name = "A_%s" % name
return name
def get_choices(choices):
converted_names = []
for value, help_text in choices.items():
if isinstance(help_text, (tuple, list)):
for choice in get_choices(help_text):
yield choice
else:
name = convert_choice_name(value)
while name in converted_names:
name += "_" + str(len(converted_names))
converted_names.append(name)
description = help_text
yield name, value, description
def convert_django_field_with_choices(field, registry=None):
if registry is not None:
converted = registry.get_converted_field(field)
if converted:
return converted
choices = getattr(field, "choices", None)
if choices:
field_class = field.owner
name = to_camel_case("{}_{}".format(field_class.__name__, field.name))
choices = list(get_choices(dict(choices)))
named_choices = [(c[0], c[1]) for c in choices]
named_choices_descriptions = {c[0]: c[2] for c in choices}
class EnumWithDescriptionsType(object):
@property
def description(self):
return named_choices_descriptions[self.name]
enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType)
converted = enum(description=field.help_text, required=field.required)
else:
converted = convert_django_field(field, registry)
if registry is not None:
registry.register_converted_field(field, converted)
return converted
@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(StringProperty)
@convert_django_field.register(RegexProperty)
def convert_field_to_string(field, registry=None):
return String(description=field.help_text)
@convert_django_field.register(IntegerProperty)
def convert_field_to_int(field, registry=None):
return Int(description=field.help_text)
@convert_django_field.register(BooleanProperty)
def convert_field_to_boolean(field, registry=None):
return NonNull(Boolean, description=field.help_text)
@convert_django_field.register(FloatProperty)
def convert_field_to_float(field, registry=None):
return Float(description=field.help_text)
@convert_django_field.register(DateTimeProperty)
def convert_datetime_to_string(field, registry=None):
return DateTime(description=field.help_text)
@convert_django_field.register(DateProperty)
def convert_date_to_string(field, registry=None):
return Date(description=field.help_text)
@convert_django_field.register(RelationshipDefinition)
def convert_onetoone_field_to_djangomodel(field, registry=None):
model = field._raw_class
manager = field.build_manager(model, 'field')
def dynamic_type():
_type = registry.get_type_for_model(manager.definition['node_class'])
if not _type:
return
if _type._meta.connection:
# Use a DjangoFilterConnectionField if there are
# defined filter_fields in the DjangoObjectType Meta
if _type._meta.neomodel_filter_fields:
from .filter.fields import DjangoFilterConnectionField # noqa
return DjangoFilterConnectionField(_type)
return DjangoConnectionField(_type)
return DjangoListField(_type)
return Dynamic(dynamic_type)
@convert_django_field.register(ArrayProperty)
def convert_array_to_list(field, registry=None):
base_property = field.base_property or StringProperty()
return List(description=field.help_text,
of_type=convert_django_field(base_property).__class__)
# @singledispatch
# def define_base_property(base_property):
# raise Exception("This property not implemented yet")
# @convert_array_to_list.register()
# def check_base_property_integer
@convert_django_field.register(JSONProperty)
@convert_django_field.register(jsonArrayProperty)
def convert_json_field_to_string(field, registry=None):
return JSONString(description=field.help_text)