diff --git a/graphene_django/forms/mutation.py b/graphene_django/forms/mutation.py index b7bf0493f..692f8d566 100644 --- a/graphene_django/forms/mutation.py +++ b/graphene_django/forms/mutation.py @@ -162,6 +162,17 @@ def __init_subclass_with_meta__( _meta=_meta, input_fields=input_fields, **options ) + @classmethod + def mutate_and_get_payload(cls, root, info, **input): + form = cls.get_form(root, info, **input) + + if form.is_valid(): + return cls.perform_mutate(form, info) + else: + errors = ErrorType.from_errors(form.errors) + + return cls(errors=errors) + @classmethod def perform_mutate(cls, form, info): obj = form.save() diff --git a/graphene_django/forms/tests/test_mutation.py b/graphene_django/forms/tests/test_mutation.py index e7dbbdfb4..093f398ce 100644 --- a/graphene_django/forms/tests/test_mutation.py +++ b/graphene_django/forms/tests/test_mutation.py @@ -29,6 +29,12 @@ class Meta: model = Pet fields = "__all__" + def clean_age(self): + age = self.cleaned_data["age"] + if age >= 99: + raise ValidationError("Too old") + return age + class PetType(DjangoObjectType): class Meta: @@ -243,6 +249,10 @@ class Mutation(ObjectType): name age } + errors { + field + messages + } } } """ @@ -255,6 +265,42 @@ class Mutation(ObjectType): self.assertEqual(pet.name, "Mia") self.assertEqual(pet.age, 10) + def test_model_form_mutation_invalid_input(self): + class PetMutation(DjangoModelFormMutation): + pet = Field(PetType) + + class Meta: + form_class = PetForm + + class Mutation(ObjectType): + pet_mutation = PetMutation.Field() + + schema = Schema(query=MockQuery, mutation=Mutation) + + result = schema.execute( + """ mutation PetMutation { + petMutation(input: { name: "Mia", age: 99 }) { + pet { + name + age + } + errors { + field + messages + } + } + } + """ + ) + self.assertIs(result.errors, None) + self.assertEqual(result.data["petMutation"]["pet"], None) + self.assertEqual( + result.data["petMutation"]["errors"], + [{"field": "age", "messages": ["Too old"],}], + ) + + self.assertEqual(Pet.objects.count(), 0) + def test_model_form_mutation_mutate_invalid_form(self): class PetMutation(DjangoModelFormMutation): class Meta: