diff --git a/graphene_django/forms/tests/test_objecttype.py b/graphene_django/forms/tests/test_objecttype.py new file mode 100644 index 0000000..d6e83ea --- /dev/null +++ b/graphene_django/forms/tests/test_objecttype.py @@ -0,0 +1,92 @@ +from django import forms +from pytest import raises + +import graphene +from graphene_django import DjangoObjectType + +from ...tests.models import CHOICES, Film, Reporter +from ..types import DjangoFormFieldObjectType, DjangoFormInputObjectType, DjangoFormObjectType, DjangoFormTypeOptions + +# Reporter a_choice CHOICES = ((1, "this"), (2, _("that"))) +THIS = CHOICES[0][0] +THIS_ON_CLIENT_CONVERTED = "A_1" + +# Film genre choices=[("do", "Documentary"), ("ac", "Action"), ("ot", "Other")], +DOCUMENTARY = "do" +DOCUMENTARY_ON_CLIENT_CONVERTED = "DO" + + +class FilmForm(forms.ModelForm): + class Meta: + model = Film + exclude = () + + +class ReporterType(DjangoObjectType): + class Meta: + model = Reporter + fields = "__all__" + + +class ReporterForm(forms.ModelForm): + class Meta: + model = Reporter + exclude = ("pets", "email", "fans") + + +class MyForm(forms.Form): + text_field = forms.CharField() + int_field = forms.IntegerField() + + +class ReporterFormType(DjangoFormObjectType): + form_class = ReporterForm + only_fields = ('pets', 'email') + + +def test_query_djangoformtype(): + class MyFormType(DjangoFormObjectType): + form_class = MyForm + + only_fields = ('text_field', 'int_field') + exclude_fields = [] + + class MockQuery(graphene.ObjectType): + form = graphene.Field( + MyFormType + ) + + @staticmethod + def resolve_form(parent, info): + return MyFormType() + + schema = graphene.Schema(query=MockQuery) + + result = schema.execute( + """ + query { + form { + fields { + name + type + } + } + } + + """ + ) + assert result.errors is None + assert result.data == { + "form": { + "fields": [ + { + "name": "text_field", + "type": "String" + }, + { + "name": "int_field", + "type": "Int" + } + ] + } + } diff --git a/graphene_django/forms/types.py b/graphene_django/forms/types.py index 0e311e5..162cf87 100644 --- a/graphene_django/forms/types.py +++ b/graphene_django/forms/types.py @@ -1,11 +1,66 @@ +from django.forms import Form import graphene from graphene import ID +from graphene.types.objecttype import ObjectType from graphene.types.inputobjecttype import InputObjectType from graphene.utils.str_converters import to_camel_case +from django.db.models import Model + from ..converter import BlankValueField -from ..types import ErrorType # noqa Import ErrorType for backwards compatibility +from ..types import DjangoObjectTypeOptions, ErrorType # noqa Import ErrorType for backwards compatibility from .mutation import fields_for_form +from graphene.types.objecttype import ObjectTypeOptions + + +class DjangoFormFieldObjectType(ObjectType): + class Meta: + form_class = Form + name = graphene.Field( + graphene.String + ) + + type = graphene.Field( + graphene.String + ) + + +class DjangoFormTypeOptions(ObjectTypeOptions): + form_class = Form + only_fields = () + exclude_fields = () + object_type = Model + + +class DjangoFormObjectType(ObjectType): + form_class = Form + only_fields = () + exclude_fields = () + + fields = graphene.List( + DjangoFormFieldObjectType + ) + + @staticmethod + def resolve_fields(parent, info): + form_class = parent.form_class + form = form_class() + only_fields = parent.only_fields + exclude_fields = parent.exclude_fields + + form_fields = fields_for_form(form, only_fields, exclude_fields) + + result = [] + + for name, field in form_fields.items(): + type = field.__class__.__name__ + result.append( + DjangoFormFieldObjectType( + name=name, + type=type + ) + ) + return result class DjangoFormInputObjectType(InputObjectType):