mirror of
				https://github.com/graphql-python/graphene-django.git
				synced 2025-11-04 01:47:57 +03:00 
			
		
		
		
	Add Django form-based mutations
This commit is contained in:
		
							parent
							
								
									f35e445963
								
							
						
					
					
						commit
						f034946cda
					
				
							
								
								
									
										1
									
								
								graphene_django/forms/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								graphene_django/forms/__init__.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					from .forms import GlobalIDFormField, GlobalIDMultipleChoiceField
 | 
				
			||||||
							
								
								
									
										90
									
								
								graphene_django/forms/converter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								graphene_django/forms/converter.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,90 @@
 | 
				
			||||||
 | 
					from django import forms
 | 
				
			||||||
 | 
					from django.core.exceptions import ImproperlyConfigured
 | 
				
			||||||
 | 
					from graphene_django.utils import import_single_dispatch
 | 
				
			||||||
 | 
					import graphene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					singledispatch = import_single_dispatch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def convert_form_to_input_type(form_class):
 | 
				
			||||||
 | 
					    form = form_class()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    items = {
 | 
				
			||||||
 | 
					        name: convert_form_field(field)
 | 
				
			||||||
 | 
					        for name, field in form.fields.items()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return type(
 | 
				
			||||||
 | 
					        '{}Input'.format(form.__class__.__name__),
 | 
				
			||||||
 | 
					        (graphene.InputObjectType, ),
 | 
				
			||||||
 | 
					        items
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@singledispatch
 | 
				
			||||||
 | 
					def get_graphene_type_from_form_field(field):
 | 
				
			||||||
 | 
					    raise ImproperlyConfigured(
 | 
				
			||||||
 | 
					        "Don't know how to convert the form field %s (%s) "
 | 
				
			||||||
 | 
					        "to Graphene type" % (field, field.__class__)
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def convert_form_field(field, is_input=True):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Converts a Django form field to a graphql field and marks the field as
 | 
				
			||||||
 | 
					    required if we are creating an input type and the field itself is required
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    graphql_type = get_graphene_type_from_form_field(field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    kwargs = {
 | 
				
			||||||
 | 
					        'description': field.help_text,
 | 
				
			||||||
 | 
					        'required': is_input and field.required,
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # if it is a tuple or a list it means that we are returning
 | 
				
			||||||
 | 
					    # the graphql type and the child type
 | 
				
			||||||
 | 
					    if isinstance(graphql_type, (list, tuple)):
 | 
				
			||||||
 | 
					        kwargs['of_type'] = graphql_type[1]
 | 
				
			||||||
 | 
					        graphql_type = graphql_type[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return graphql_type(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.CharField)
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.ChoiceField)
 | 
				
			||||||
 | 
					def convert_form_field_to_string(field):
 | 
				
			||||||
 | 
					    return graphene.String
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.IntegerField)
 | 
				
			||||||
 | 
					def convert_form_field_to_int(field):
 | 
				
			||||||
 | 
					    return graphene.Int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.BooleanField)
 | 
				
			||||||
 | 
					def convert_form_field_to_bool(field):
 | 
				
			||||||
 | 
					    return graphene.Boolean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.FloatField)
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.DecimalField)
 | 
				
			||||||
 | 
					def convert_form_field_to_float(field):
 | 
				
			||||||
 | 
					    return graphene.Float
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.DateField)
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.DateTimeField)
 | 
				
			||||||
 | 
					def convert_form_field_to_datetime(field):
 | 
				
			||||||
 | 
					    return graphene.types.datetime.DateTime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.TimeField)
 | 
				
			||||||
 | 
					def convert_form_field_to_time(field):
 | 
				
			||||||
 | 
					    return graphene.types.datetime.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@get_graphene_type_from_form_field.register(forms.MultipleChoiceField)
 | 
				
			||||||
 | 
					def convert_form_field_to_list_of_string(field):
 | 
				
			||||||
 | 
					    return (graphene.List, graphene.String)
 | 
				
			||||||
							
								
								
									
										157
									
								
								graphene_django/forms/mutation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								graphene_django/forms/mutation.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,157 @@
 | 
				
			||||||
 | 
					from functools import partial
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import six
 | 
				
			||||||
 | 
					import graphene
 | 
				
			||||||
 | 
					from graphene import Field, Argument
 | 
				
			||||||
 | 
					from graphene.types.mutation import MutationMeta
 | 
				
			||||||
 | 
					from graphene.types.objecttype import ObjectTypeMeta
 | 
				
			||||||
 | 
					from graphene.types.options import Options
 | 
				
			||||||
 | 
					from graphene.types.utils import get_field_as, merge
 | 
				
			||||||
 | 
					from graphene.utils.is_base_type import is_base_type
 | 
				
			||||||
 | 
					from graphene_django.registry import get_global_registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .converter import convert_form_to_input_type
 | 
				
			||||||
 | 
					from .types import ErrorType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FormMutationMeta(MutationMeta):
 | 
				
			||||||
 | 
					    def __new__(cls, name, bases, attrs):
 | 
				
			||||||
 | 
					        if not is_base_type(bases, FormMutationMeta):
 | 
				
			||||||
 | 
					            return type.__new__(cls, name, bases, attrs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        options = Options(
 | 
				
			||||||
 | 
					            attrs.pop('Meta', None),
 | 
				
			||||||
 | 
					            name=name,
 | 
				
			||||||
 | 
					            description=attrs.pop('__doc__', None),
 | 
				
			||||||
 | 
					            form_class=None,
 | 
				
			||||||
 | 
					            input_field_name='input',
 | 
				
			||||||
 | 
					            local_fields=None,
 | 
				
			||||||
 | 
					            only_fields=(),
 | 
				
			||||||
 | 
					            exclude_fields=(),
 | 
				
			||||||
 | 
					            interfaces=(),
 | 
				
			||||||
 | 
					            registry=None
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not options.form_class:
 | 
				
			||||||
 | 
					            raise Exception('Missing form_class')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cls = ObjectTypeMeta.__new__(
 | 
				
			||||||
 | 
					            cls, name, bases, dict(attrs, _meta=options)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        options.fields = merge(
 | 
				
			||||||
 | 
					            options.interface_fields, options.base_fields, options.local_fields,
 | 
				
			||||||
 | 
					            {'errors': get_field_as(cls.errors, Field)}
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cls.Input = convert_form_to_input_type(options.form_class)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        field_kwargs = {cls.options.input_field_name: Argument(cls.Input, required=True)}
 | 
				
			||||||
 | 
					        cls.Field = partial(
 | 
				
			||||||
 | 
					            Field,
 | 
				
			||||||
 | 
					            cls,
 | 
				
			||||||
 | 
					            resolver=cls.mutate,
 | 
				
			||||||
 | 
					            **field_kwargs
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cls
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BaseFormMutation(graphene.Mutation):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def mutate(cls, root, args, context, info):
 | 
				
			||||||
 | 
					        form = cls.get_form(root, args, context, info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if form.is_valid():
 | 
				
			||||||
 | 
					            return cls.perform_mutate(form, info)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            errors = [
 | 
				
			||||||
 | 
					                ErrorType(field=key, messages=value)
 | 
				
			||||||
 | 
					                for key, value in form.errors.items()
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					            return cls(errors=errors)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def perform_mutate(cls, form, info):
 | 
				
			||||||
 | 
					        form.save()
 | 
				
			||||||
 | 
					        return cls(errors=[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def get_form(cls, root, args, context, info):
 | 
				
			||||||
 | 
					        form_data = args.get(cls._meta.input_field_name)
 | 
				
			||||||
 | 
					        kwargs = cls.get_form_kwargs(root, args, context, info)
 | 
				
			||||||
 | 
					        return cls._meta.form_class(data=form_data, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def get_form_kwargs(cls, root, args, context, info):
 | 
				
			||||||
 | 
					        return {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FormMutation(six.with_metaclass(FormMutationMeta, BaseFormMutation)):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    errors = graphene.List(ErrorType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ModelFormMutationMeta(MutationMeta):
 | 
				
			||||||
 | 
					    def __new__(cls, name, bases, attrs):
 | 
				
			||||||
 | 
					        if not is_base_type(bases, ModelFormMutationMeta):
 | 
				
			||||||
 | 
					            return type.__new__(cls, name, bases, attrs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        options = Options(
 | 
				
			||||||
 | 
					            attrs.pop('Meta', None),
 | 
				
			||||||
 | 
					            name=name,
 | 
				
			||||||
 | 
					            description=attrs.pop('__doc__', None),
 | 
				
			||||||
 | 
					            form_class=None,
 | 
				
			||||||
 | 
					            input_field_name='input',
 | 
				
			||||||
 | 
					            return_field_name=None,
 | 
				
			||||||
 | 
					            model=None,
 | 
				
			||||||
 | 
					            local_fields=None,
 | 
				
			||||||
 | 
					            only_fields=(),
 | 
				
			||||||
 | 
					            exclude_fields=(),
 | 
				
			||||||
 | 
					            interfaces=(),
 | 
				
			||||||
 | 
					            registry=None
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not options.form_class:
 | 
				
			||||||
 | 
					            raise Exception('Missing form_class')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cls = ObjectTypeMeta.__new__(
 | 
				
			||||||
 | 
					            cls, name, bases, dict(attrs, _meta=options)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        options.fields = merge(
 | 
				
			||||||
 | 
					            options.interface_fields, options.base_fields, options.local_fields,
 | 
				
			||||||
 | 
					            {'errors': get_field_as(cls.errors, Field)}
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cls.Input = convert_form_to_input_type(options.form_class)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        field_kwargs = {cls.options.input_field_name: Argument(cls.Input, required=True)}
 | 
				
			||||||
 | 
					        cls.Field = partial(
 | 
				
			||||||
 | 
					            Field,
 | 
				
			||||||
 | 
					            cls,
 | 
				
			||||||
 | 
					            resolver=cls.mutate,
 | 
				
			||||||
 | 
					            **field_kwargs
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cls.model = options.model or options.form_class.Meta.model
 | 
				
			||||||
 | 
					        cls.return_field_name = cls._meta.return_field_name or cls.model._meta.model_name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        registry = get_global_registry()
 | 
				
			||||||
 | 
					        model_type = registry.get_type_for_model(cls.model)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        options.fields[cls.return_field_name] = graphene.Field(model_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return cls
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ModelFormMutation(six.with_metaclass(ModelFormMutationMeta, BaseFormMutation)):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    errors = graphene.List(ErrorType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def perform_mutate(cls, form, info):
 | 
				
			||||||
 | 
					        obj = form.save()
 | 
				
			||||||
 | 
					        kwargs = {cls.return_field_name: obj}
 | 
				
			||||||
 | 
					        return cls(errors=[], **kwargs)
 | 
				
			||||||
							
								
								
									
										0
									
								
								graphene_django/forms/tests/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								graphene_django/forms/tests/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										98
									
								
								graphene_django/forms/tests/test_coverter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								graphene_django/forms/tests/test_coverter.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,98 @@
 | 
				
			||||||
 | 
					import copy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django import forms
 | 
				
			||||||
 | 
					from py.test import raises
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import graphene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ..converter import convert_form_field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _get_type(form_field, **kwargs):
 | 
				
			||||||
 | 
					    # prevents the following error:
 | 
				
			||||||
 | 
					    # AssertionError: The `source` argument is not meaningful when applied to a `child=` field.
 | 
				
			||||||
 | 
					    # Remove `source=` from the field declaration.
 | 
				
			||||||
 | 
					    # since we are reusing the same child in when testing the required attribute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'child' in kwargs:
 | 
				
			||||||
 | 
					        kwargs['child'] = copy.deepcopy(kwargs['child'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    field = form_field(**kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return convert_form_field(field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def assert_conversion(form_field, graphene_field, **kwargs):
 | 
				
			||||||
 | 
					    graphene_type = _get_type(form_field, help_text='Custom Help Text', **kwargs)
 | 
				
			||||||
 | 
					    assert isinstance(graphene_type, graphene_field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    graphene_type_required = _get_type(
 | 
				
			||||||
 | 
					        form_field, help_text='Custom Help Text', required=True, **kwargs
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    assert isinstance(graphene_type_required, graphene_field)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return graphene_type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_unknown_form_field_raise_exception():
 | 
				
			||||||
 | 
					    with raises(Exception) as excinfo:
 | 
				
			||||||
 | 
					        convert_form_field(None)
 | 
				
			||||||
 | 
					    assert 'Don\'t know how to convert the form field' in str(excinfo.value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_charfield_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.CharField, graphene.String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_timefield_convert_time():
 | 
				
			||||||
 | 
					    assert_conversion(forms.TimeField, graphene.types.datetime.Time)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_email_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.EmailField, graphene.String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_slug_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.SlugField, graphene.String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_url_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.URLField, graphene.String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_choicefield_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.ChoiceField, graphene.String, choices=[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_regexfield_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.RegexField, graphene.String, regex='[0-9]+')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_uuidfield_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.UUIDField, graphene.String)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_integer_convert_int():
 | 
				
			||||||
 | 
					    assert_conversion(forms.IntegerField, graphene.Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_boolean_convert_boolean():
 | 
				
			||||||
 | 
					    assert_conversion(forms.BooleanField, graphene.Boolean)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_float_convert_float():
 | 
				
			||||||
 | 
					    assert_conversion(forms.FloatField, graphene.Float)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_decimal_convert_float():
 | 
				
			||||||
 | 
					    assert_conversion(forms.DecimalField, graphene.Float, max_digits=4, decimal_places=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_filepath_convert_string():
 | 
				
			||||||
 | 
					    assert_conversion(forms.FilePathField, graphene.String, path='/')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_should_multiplechoicefield_convert_to_list_of_string():
 | 
				
			||||||
 | 
					    field = assert_conversion(forms.MultipleChoiceField, graphene.List, choices=[1, 2, 3])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert field.of_type == graphene.String
 | 
				
			||||||
							
								
								
									
										49
									
								
								graphene_django/forms/tests/test_mutation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								graphene_django/forms/tests/test_mutation.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					from django import forms
 | 
				
			||||||
 | 
					from py.test import raises
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from graphene_django.tests.models import Pet
 | 
				
			||||||
 | 
					from ..mutation import FormMutation, ModelFormMutation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MyForm(forms.Form):
 | 
				
			||||||
 | 
					    text = forms.CharField()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PetForm(forms.ModelForm):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        model = Pet
 | 
				
			||||||
 | 
					        fields = ('name',)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_needs_form_class():
 | 
				
			||||||
 | 
					    with raises(Exception) as exc:
 | 
				
			||||||
 | 
					        class MyMutation(FormMutation):
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert exc.value.args[0] == 'Missing form_class'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_has_fields():
 | 
				
			||||||
 | 
					    class MyMutation(FormMutation):
 | 
				
			||||||
 | 
					        class Meta:
 | 
				
			||||||
 | 
					            form_class = MyForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert 'errors' in MyMutation._meta.fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_has_input_fields():
 | 
				
			||||||
 | 
					    class MyMutation(FormMutation):
 | 
				
			||||||
 | 
					        class Meta:
 | 
				
			||||||
 | 
					            form_class = MyForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert 'text' in MyMutation.Input._meta.fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_model_form():
 | 
				
			||||||
 | 
					    class PetMutation(ModelFormMutation):
 | 
				
			||||||
 | 
					        class Meta:
 | 
				
			||||||
 | 
					            form_class = PetForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert PetMutation.model == Pet
 | 
				
			||||||
 | 
					    assert PetMutation.return_field_name == 'pet'
 | 
				
			||||||
							
								
								
									
										6
									
								
								graphene_django/forms/types.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								graphene_django/forms/types.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					import graphene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ErrorType(graphene.ObjectType):
 | 
				
			||||||
 | 
					    field = graphene.String()
 | 
				
			||||||
 | 
					    messages = graphene.List(graphene.String)
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user