Support instance kwarg

This commit is contained in:
Grant McConnaughey 2017-11-29 14:12:02 -06:00
parent bf7ad7eeda
commit 40610c64a3
2 changed files with 52 additions and 22 deletions

View File

@ -27,13 +27,13 @@ def fields_for_form(form, only_fields, exclude_fields):
return fields return fields
class BaseFormMutation(ClientIDMutation): class BaseDjangoFormMutation(ClientIDMutation):
class Meta: class Meta:
abstract = True abstract = True
@classmethod @classmethod
def mutate_and_get_payload(cls, root, info, **input): def mutate_and_get_payload(cls, root, info, **input):
form = cls._meta.form_class(data=input) form = cls.get_form(root, info, **input)
if form.is_valid(): if form.is_valid():
return cls.perform_mutate(form, info) return cls.perform_mutate(form, info)
@ -45,12 +45,28 @@ class BaseFormMutation(ClientIDMutation):
return cls(errors=errors) return cls(errors=errors)
@classmethod
def get_form(cls, root, info, **input):
form_kwargs = cls.get_form_kwargs(root, info, **input)
return cls._meta.form_class(**form_kwargs)
class FormMutationOptions(MutationOptions): @classmethod
def get_form_kwargs(cls, root, info, **input):
kwargs = {'data': input}
pk = input.pop('id', None)
if pk:
instance = cls._meta.model._default_manager.get(pk=pk)
kwargs['instance'] = instance
return kwargs
class DjangoFormMutationOptions(MutationOptions):
form_class = None form_class = None
class FormMutation(BaseFormMutation): class DjangoFormMutation(BaseDjangoFormMutation):
class Meta: class Meta:
abstract = True abstract = True
@ -67,7 +83,7 @@ class FormMutation(BaseFormMutation):
input_fields = fields_for_form(form, only_fields, exclude_fields) input_fields = fields_for_form(form, only_fields, exclude_fields)
output_fields = fields_for_form(form, only_fields, exclude_fields) output_fields = fields_for_form(form, only_fields, exclude_fields)
_meta = FormMutationOptions(cls) _meta = DjangoFormMutationOptions(cls)
_meta.form_class = form_class _meta.form_class = form_class
_meta.fields = yank_fields_from_attrs( _meta.fields = yank_fields_from_attrs(
output_fields, output_fields,
@ -78,7 +94,7 @@ class FormMutation(BaseFormMutation):
input_fields, input_fields,
_as=InputField, _as=InputField,
) )
super(FormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options) super(DjangoFormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options)
@classmethod @classmethod
def perform_mutate(cls, form, info): def perform_mutate(cls, form, info):
@ -86,12 +102,12 @@ class FormMutation(BaseFormMutation):
return cls(errors=[]) return cls(errors=[])
class ModelFormMutationOptions(FormMutationOptions): class DjangoModelDjangoFormMutationOptions(DjangoFormMutationOptions):
model = None model = None
return_field_name = None return_field_name = None
class ModelFormMutation(BaseFormMutation): class DjangoModelFormMutation(BaseDjangoFormMutation):
class Meta: class Meta:
abstract = True abstract = True
@ -102,13 +118,13 @@ class ModelFormMutation(BaseFormMutation):
only_fields=(), exclude_fields=(), **options): only_fields=(), exclude_fields=(), **options):
if not form_class: if not form_class:
raise Exception('form_class is required for ModelFormMutation') raise Exception('form_class is required for DjangoModelFormMutation')
if not model: if not model:
model = form_class._meta.model model = form_class._meta.model
if not model: if not model:
raise Exception('model is required for ModelFormMutation') raise Exception('model is required for DjangoModelFormMutation')
form = form_class() form = form_class()
input_fields = fields_for_form(form, only_fields, exclude_fields) input_fields = fields_for_form(form, only_fields, exclude_fields)
@ -119,7 +135,7 @@ class ModelFormMutation(BaseFormMutation):
output_fields = OrderedDict() output_fields = OrderedDict()
output_fields[return_field_name] = graphene.Field(model_type) output_fields[return_field_name] = graphene.Field(model_type)
_meta = ModelFormMutationOptions(cls) _meta = DjangoModelDjangoFormMutationOptions(cls)
_meta.form_class = form_class _meta.form_class = form_class
_meta.model = model _meta.model = model
_meta.return_field_name = return_field_name _meta.return_field_name = return_field_name
@ -132,7 +148,7 @@ class ModelFormMutation(BaseFormMutation):
input_fields, input_fields,
_as=InputField, _as=InputField,
) )
super(ModelFormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options) super(DjangoModelFormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options)
@classmethod @classmethod
def perform_mutate(cls, form, info): def perform_mutate(cls, form, info):

View File

@ -3,7 +3,7 @@ from django.test import TestCase
from py.test import raises from py.test import raises
from graphene_django.tests.models import Pet, Film from graphene_django.tests.models import Pet, Film
from ..mutation import FormMutation, ModelFormMutation from ..mutation import DjangoFormMutation, DjangoModelFormMutation
class MyForm(forms.Form): class MyForm(forms.Form):
@ -19,14 +19,14 @@ class PetForm(forms.ModelForm):
def test_needs_form_class(): def test_needs_form_class():
with raises(Exception) as exc: with raises(Exception) as exc:
class MyMutation(FormMutation): class MyMutation(DjangoFormMutation):
pass pass
assert exc.value.args[0] == 'form_class is required for FormMutation' assert exc.value.args[0] == 'form_class is required for FormMutation'
def test_has_output_fields(): def test_has_output_fields():
class MyMutation(FormMutation): class MyMutation(DjangoFormMutation):
class Meta: class Meta:
form_class = MyForm form_class = MyForm
@ -34,7 +34,7 @@ def test_has_output_fields():
def test_has_input_fields(): def test_has_input_fields():
class MyMutation(FormMutation): class MyMutation(DjangoFormMutation):
class Meta: class Meta:
form_class = MyForm form_class = MyForm
@ -44,7 +44,7 @@ def test_has_input_fields():
class ModelFormMutationTests(TestCase): class ModelFormMutationTests(TestCase):
def test_default_meta_fields(self): def test_default_meta_fields(self):
class PetMutation(ModelFormMutation): class PetMutation(DjangoModelFormMutation):
class Meta: class Meta:
form_class = PetForm form_class = PetForm
@ -53,7 +53,7 @@ class ModelFormMutationTests(TestCase):
self.assertIn('pet', PetMutation._meta.fields) self.assertIn('pet', PetMutation._meta.fields)
def test_custom_return_field_name(self): def test_custom_return_field_name(self):
class PetMutation(ModelFormMutation): class PetMutation(DjangoModelFormMutation):
class Meta: class Meta:
form_class = PetForm form_class = PetForm
model = Film model = Film
@ -64,19 +64,33 @@ class ModelFormMutationTests(TestCase):
self.assertIn('animal', PetMutation._meta.fields) self.assertIn('animal', PetMutation._meta.fields)
def test_model_form_mutation_mutate(self): def test_model_form_mutation_mutate(self):
class PetMutation(ModelFormMutation): class PetMutation(DjangoModelFormMutation):
class Meta: class Meta:
form_class = PetForm form_class = PetForm
result = PetMutation.mutate_and_get_payload(None, None, name='Fluffy') pet = Pet.objects.create(name='Axel')
result = PetMutation.mutate_and_get_payload(None, None, id=pet.pk, name='Mia')
self.assertEqual(Pet.objects.count(), 1)
pet.refresh_from_db()
self.assertEqual(pet.name, 'Mia')
self.assertEqual(result.errors, [])
def test_model_form_mutation_updates_existing_(self):
class PetMutation(DjangoModelFormMutation):
class Meta:
form_class = PetForm
result = PetMutation.mutate_and_get_payload(None, None, name='Mia')
self.assertEqual(Pet.objects.count(), 1) self.assertEqual(Pet.objects.count(), 1)
pet = Pet.objects.get() pet = Pet.objects.get()
self.assertEqual(pet.name, 'Fluffy') self.assertEqual(pet.name, 'Mia')
self.assertEqual(result.errors, []) self.assertEqual(result.errors, [])
def test_model_form_mutation_mutate_invalid_form(self): def test_model_form_mutation_mutate_invalid_form(self):
class PetMutation(ModelFormMutation): class PetMutation(DjangoModelFormMutation):
class Meta: class Meta:
form_class = PetForm form_class = PetForm