add a new subclass and a few tests [WIP]

This commit is contained in:
colan 2017-04-26 23:11:35 -04:00
parent 1e34dfb3e5
commit ff69b07267
2 changed files with 156 additions and 0 deletions

View File

@ -0,0 +1,60 @@
import collections
from graphene_django import converter, utils
from graphene.types.utils import merge
from graphene.utils.is_base_type import is_base_type
def convert_fields(model, only_fields, exclude_fields):
model_fields = utils.get_model_fields(model=model)
fields = collections.OrderedDict()
for name, field in model_fields:
is_not_in_only = only_fields and name not in only_fields
is_already_created = name in model_fields
is_excluded = name in exclude_fields or is_already_created
# https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_query_name
is_no_backref = str(name).endswith('+')
if is_not_in_only or is_excluded or is_no_backref:
# We skip this field if we specify only_fields and is not
# in there. Or when we exclude this field in exclude_fields.
# Or when there is no back reference.
continue
converted = converter.convert_django_field(field, None)
if not converted:
continue
fields[name] = converted
print(fields)
return fields
class DjangoModelInputMeta(type):
@staticmethod
def __new__(cls, name, bases, attrs):
# We'll get called also for non-user classes like DjangoModelInput. Only
# kick in when called for a sub-class.
if not is_base_type(bases, DjangoModelInputMeta):
return type.__new__(cls, name, bases, attrs)
# Pop Meta info. Must be removed from class, otherwise graphene will
# complain.
meta = attrs.pop('Meta')
if not hasattr(meta, 'exclude_fields'):
setattr(meta, 'exclude_fields', ())
if not hasattr(meta, 'only_fields'):
setattr(meta, 'only_fields', ())
fields = convert_fields(model=meta.model, only_fields=meta.only_fields, exclude_fields=meta.exclude_fields)
attrs = merge(attrs, fields)
return type.__new__(cls, name, bases, attrs)
class DjangoModelInput(metaclass=DjangoModelInputMeta):
"""
Derive a mutation's Input class from this and define a meta class with
`model` and `only_fields` members. This will populate the input class
with the converted django members.
"""
pass

View File

@ -0,0 +1,96 @@
from mock import patch
from graphene import ObjectType, Schema, Mutation, String
from .. import registry
from ..input_types import DjangoModelInput
from .models import Reporter as ReporterModel
def test_mutation_execution_with_exclude_fields():
registry.reset_global_registry()
class CreateReporter(Mutation):
first_name = String()
last_name = String()
email = String()
class Input(DjangoModelInput):
class Meta:
model = ReporterModel
exclude_fields = ('id', 'pets', 'a_choice', 'films', 'articles')
def mutate(self, args, context, info):
first_name = args.get('first_name')
last_name = args.get('last_name')
email = args.get('email')
return CreateReporter(first_name=first_name, last_name=last_name, email=email)
class MyMutation(ObjectType):
reporter_input = CreateReporter.Field()
class Query(ObjectType):
a = String()
schema = Schema(query=Query, mutation=MyMutation)
result = schema.execute(''' mutation mymutation {
reporterInput(firstName:"Peter", lastName: "test", email: "test@test.com") {
firstName
lastName
email
}
}
''')
assert not result.errors
assert result.data == {
'reporterInput': {
'firstName': 'Peter',
'lastName': 'test',
'email': "test@test.com"
}
}
def test_mutation_execution():
registry.reset_global_registry()
class ReporterInput(Mutation):
first_name = String()
last_name = String()
class Input(DjangoModelInput):
class Meta:
model = ReporterModel
only_fields = ('first_name', 'last_name')
def mutate(self, args, context, info):
first_name = args.get('first_name')
last_name = args.get('last_name')
return ReporterInput(first_name=first_name, last_name=last_name)
class MyMutation(ObjectType):
reporter_input = ReporterInput.Field()
class Query(ObjectType):
a = String()
schema = Schema(query=Query, mutation=MyMutation)
result = schema.execute(''' mutation mymutation {
reporterInput(firstName:"Peter", lastName: "test") {
firstName
lastName
}
}
''')
assert not result.errors
assert result.data == {
'reporterInput': {
'firstName': 'Peter',
'lastName': 'test',
}
}