mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-23 07:00:56 +03:00
Implicitly mark Django fields as NonNull where appropriate
This commit is contained in:
parent
8711dd20b6
commit
0c63b0c5e2
|
@ -3,7 +3,7 @@ from django.utils.encoding import force_text
|
|||
|
||||
from ...core.classtypes.enum import Enum
|
||||
from ...core.types.custom_scalars import DateTime, JSONString
|
||||
from ...core.types.definitions import List
|
||||
from ...core.types.definitions import NonNull, List
|
||||
from ...core.types.scalars import ID, Boolean, Float, Int, String
|
||||
from ...utils import to_const
|
||||
from .compat import (ArrayField, HStoreField, JSONField, RangeField,
|
||||
|
@ -32,6 +32,17 @@ def convert_django_field_with_choices(field):
|
|||
return convert_django_field(field)
|
||||
|
||||
|
||||
def add_nonnull_to_field(convert_field):
|
||||
def convert_django_nonnull_field(field):
|
||||
graphene_type = convert_field(field)
|
||||
if isinstance(field, models.ManyToOneRel):
|
||||
is_null = field.field.null
|
||||
else:
|
||||
is_null = field.null
|
||||
return graphene_type if is_null else NonNull(graphene_type)
|
||||
return convert_django_nonnull_field
|
||||
|
||||
|
||||
@singledispatch
|
||||
def convert_django_field(field):
|
||||
raise Exception(
|
||||
|
@ -47,11 +58,13 @@ def convert_django_field(field):
|
|||
@convert_django_field.register(models.GenericIPAddressField)
|
||||
@convert_django_field.register(models.FileField)
|
||||
@convert_django_field.register(UUIDField)
|
||||
@add_nonnull_to_field
|
||||
def convert_field_to_string(field):
|
||||
return String(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.AutoField)
|
||||
@add_nonnull_to_field
|
||||
def convert_field_to_id(field):
|
||||
return ID(description=field.help_text)
|
||||
|
||||
|
@ -61,11 +74,13 @@ def convert_field_to_id(field):
|
|||
@convert_django_field.register(models.SmallIntegerField)
|
||||
@convert_django_field.register(models.BigIntegerField)
|
||||
@convert_django_field.register(models.IntegerField)
|
||||
@add_nonnull_to_field
|
||||
def convert_field_to_int(field):
|
||||
return Int(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.BooleanField)
|
||||
@add_nonnull_to_field
|
||||
def convert_field_to_boolean(field):
|
||||
return Boolean(description=field.help_text, required=True)
|
||||
|
||||
|
@ -77,16 +92,19 @@ def convert_field_to_nullboolean(field):
|
|||
|
||||
@convert_django_field.register(models.DecimalField)
|
||||
@convert_django_field.register(models.FloatField)
|
||||
@add_nonnull_to_field
|
||||
def convert_field_to_float(field):
|
||||
return Float(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.DateField)
|
||||
@add_nonnull_to_field
|
||||
def convert_date_to_string(field):
|
||||
return DateTime(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(models.OneToOneRel)
|
||||
@add_nonnull_to_field
|
||||
def convert_onetoone_field_to_djangomodel(field):
|
||||
from .fields import DjangoModelField
|
||||
return DjangoModelField(get_related_model(field))
|
||||
|
@ -107,12 +125,13 @@ def convert_relatedfield_to_djangomodel(field):
|
|||
from .fields import DjangoModelField, ConnectionOrListField
|
||||
model_field = DjangoModelField(field.model)
|
||||
if isinstance(field.field, models.OneToOneField):
|
||||
return model_field
|
||||
return model_field if field.field.null else NonNull(model_field)
|
||||
return ConnectionOrListField(model_field)
|
||||
|
||||
|
||||
@convert_django_field.register(models.OneToOneField)
|
||||
@convert_django_field.register(models.ForeignKey)
|
||||
@add_nonnull_to_field
|
||||
def convert_field_to_djangomodel(field):
|
||||
from .fields import DjangoModelField
|
||||
return DjangoModelField(get_related_model(field), description=field.help_text)
|
||||
|
@ -126,11 +145,13 @@ def convert_postgres_array_to_list(field):
|
|||
|
||||
@convert_django_field.register(HStoreField)
|
||||
@convert_django_field.register(JSONField)
|
||||
@add_nonnull_to_field
|
||||
def convert_posgres_field_to_string(field):
|
||||
return JSONString(description=field.help_text)
|
||||
|
||||
|
||||
@convert_django_field.register(RangeField)
|
||||
@add_nonnull_to_field
|
||||
def convert_posgres_range_to_string(field):
|
||||
inner_type = convert_django_field(field.base_field)
|
||||
return List(inner_type, description=field.help_text)
|
||||
|
|
|
@ -35,7 +35,7 @@ class Reporter(models.Model):
|
|||
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(max_length=100)
|
||||
headline = models.CharField(max_length=100, null=True)
|
||||
pub_date = models.DateField()
|
||||
reporter = models.ForeignKey(Reporter, related_name='articles')
|
||||
lang = models.CharField(max_length=2, help_text='Language', choices=[
|
||||
|
|
|
@ -5,6 +5,7 @@ from py.test import raises
|
|||
|
||||
import graphene
|
||||
from graphene.core.types.custom_scalars import DateTime, JSONString
|
||||
from graphene.core.types.definitions import OfType
|
||||
|
||||
from ..compat import (ArrayField, HStoreField, JSONField, MissingType,
|
||||
RangeField)
|
||||
|
@ -14,11 +15,16 @@ from .models import Article, Reporter, Film, FilmDetails
|
|||
|
||||
|
||||
def assert_conversion(django_field, graphene_field, *args, **kwargs):
|
||||
field = django_field(help_text='Custom Help Text', *args, **kwargs)
|
||||
field = django_field(help_text='Custom Help Text', null=True, *args, **kwargs)
|
||||
graphene_type = convert_django_field(field)
|
||||
assert isinstance(graphene_type, graphene_field)
|
||||
field = graphene_type.as_field()
|
||||
assert field.description == 'Custom Help Text'
|
||||
if not isinstance(graphene_type, OfType):
|
||||
nonnull_field = django_field(null=False, *args, **kwargs)
|
||||
if not nonnull_field.null:
|
||||
nonnull_graphene_type = convert_django_field(nonnull_field)
|
||||
assert isinstance(nonnull_graphene_type, graphene.NonNull)
|
||||
return field
|
||||
|
||||
|
||||
|
@ -176,8 +182,9 @@ def test_should_onetoone_reverse_convert_model():
|
|||
related = getattr(Film.details, 'rel', None) or \
|
||||
getattr(Film.details, 'related')
|
||||
graphene_type = convert_django_field(related)
|
||||
assert isinstance(graphene_type, DjangoModelField)
|
||||
assert graphene_type.model == FilmDetails
|
||||
assert isinstance(graphene_type, graphene.NonNull)
|
||||
assert isinstance(graphene_type.of_type, DjangoModelField)
|
||||
assert graphene_type.of_type.model == FilmDetails
|
||||
|
||||
|
||||
def test_should_onetoone_convert_model():
|
||||
|
@ -195,7 +202,8 @@ def test_should_foreignkey_convert_model():
|
|||
def test_should_postgres_array_convert_list():
|
||||
field = assert_conversion(ArrayField, graphene.List, models.CharField(max_length=100))
|
||||
assert isinstance(field.type, graphene.List)
|
||||
assert isinstance(field.type.of_type, graphene.String)
|
||||
assert isinstance(field.type.of_type, graphene.NonNull)
|
||||
assert isinstance(field.type.of_type.of_type, graphene.String)
|
||||
|
||||
|
||||
@pytest.mark.skipif(ArrayField is MissingType,
|
||||
|
@ -204,7 +212,8 @@ def test_should_postgres_array_multiple_convert_list():
|
|||
field = assert_conversion(ArrayField, graphene.List, ArrayField(models.CharField(max_length=100)))
|
||||
assert isinstance(field.type, graphene.List)
|
||||
assert isinstance(field.type.of_type, graphene.List)
|
||||
assert isinstance(field.type.of_type.of_type, graphene.String)
|
||||
assert isinstance(field.type.of_type.of_type, graphene.NonNull)
|
||||
assert isinstance(field.type.of_type.of_type.of_type, graphene.String)
|
||||
|
||||
|
||||
@pytest.mark.skipif(HStoreField is MissingType,
|
||||
|
@ -224,4 +233,5 @@ def test_should_postgres_json_convert_string():
|
|||
def test_should_postgres_range_convert_list():
|
||||
from django.contrib.postgres.fields import IntegerRangeField
|
||||
field = assert_conversion(IntegerRangeField, graphene.List)
|
||||
assert isinstance(field.type.of_type, graphene.Int)
|
||||
assert isinstance(field.type.of_type, graphene.NonNull)
|
||||
assert isinstance(field.type.of_type.of_type, graphene.Int)
|
||||
|
|
Loading…
Reference in New Issue
Block a user