Skip to content

Commit 40610c6

Browse files
author
Grant McConnaughey
committed
Support instance kwarg
1 parent bf7ad7e commit 40610c6

File tree

2 files changed

+52
-22
lines changed

2 files changed

+52
-22
lines changed

graphene_django/forms/mutation.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ def fields_for_form(form, only_fields, exclude_fields):
2727
return fields
2828

2929

30-
class BaseFormMutation(ClientIDMutation):
30+
class BaseDjangoFormMutation(ClientIDMutation):
3131
class Meta:
3232
abstract = True
3333

3434
@classmethod
3535
def mutate_and_get_payload(cls, root, info, **input):
36-
form = cls._meta.form_class(data=input)
36+
form = cls.get_form(root, info, **input)
3737

3838
if form.is_valid():
3939
return cls.perform_mutate(form, info)
@@ -45,12 +45,28 @@ def mutate_and_get_payload(cls, root, info, **input):
4545

4646
return cls(errors=errors)
4747

48+
@classmethod
49+
def get_form(cls, root, info, **input):
50+
form_kwargs = cls.get_form_kwargs(root, info, **input)
51+
return cls._meta.form_class(**form_kwargs)
52+
53+
@classmethod
54+
def get_form_kwargs(cls, root, info, **input):
55+
kwargs = {'data': input}
56+
57+
pk = input.pop('id', None)
58+
if pk:
59+
instance = cls._meta.model._default_manager.get(pk=pk)
60+
kwargs['instance'] = instance
61+
62+
return kwargs
63+
4864

49-
class FormMutationOptions(MutationOptions):
65+
class DjangoFormMutationOptions(MutationOptions):
5066
form_class = None
5167

5268

53-
class FormMutation(BaseFormMutation):
69+
class DjangoFormMutation(BaseDjangoFormMutation):
5470
class Meta:
5571
abstract = True
5672

@@ -67,7 +83,7 @@ def __init_subclass_with_meta__(cls, form_class=None,
6783
input_fields = fields_for_form(form, only_fields, exclude_fields)
6884
output_fields = fields_for_form(form, only_fields, exclude_fields)
6985

70-
_meta = FormMutationOptions(cls)
86+
_meta = DjangoFormMutationOptions(cls)
7187
_meta.form_class = form_class
7288
_meta.fields = yank_fields_from_attrs(
7389
output_fields,
@@ -78,20 +94,20 @@ def __init_subclass_with_meta__(cls, form_class=None,
7894
input_fields,
7995
_as=InputField,
8096
)
81-
super(FormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options)
97+
super(DjangoFormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options)
8298

8399
@classmethod
84100
def perform_mutate(cls, form, info):
85101
form.save()
86102
return cls(errors=[])
87103

88104

89-
class ModelFormMutationOptions(FormMutationOptions):
105+
class DjangoModelDjangoFormMutationOptions(DjangoFormMutationOptions):
90106
model = None
91107
return_field_name = None
92108

93109

94-
class ModelFormMutation(BaseFormMutation):
110+
class DjangoModelFormMutation(BaseDjangoFormMutation):
95111
class Meta:
96112
abstract = True
97113

@@ -102,13 +118,13 @@ def __init_subclass_with_meta__(cls, form_class=None, model=None, return_field_n
102118
only_fields=(), exclude_fields=(), **options):
103119

104120
if not form_class:
105-
raise Exception('form_class is required for ModelFormMutation')
121+
raise Exception('form_class is required for DjangoModelFormMutation')
106122

107123
if not model:
108124
model = form_class._meta.model
109125

110126
if not model:
111-
raise Exception('model is required for ModelFormMutation')
127+
raise Exception('model is required for DjangoModelFormMutation')
112128

113129
form = form_class()
114130
input_fields = fields_for_form(form, only_fields, exclude_fields)
@@ -119,7 +135,7 @@ def __init_subclass_with_meta__(cls, form_class=None, model=None, return_field_n
119135
output_fields = OrderedDict()
120136
output_fields[return_field_name] = graphene.Field(model_type)
121137

122-
_meta = ModelFormMutationOptions(cls)
138+
_meta = DjangoModelDjangoFormMutationOptions(cls)
123139
_meta.form_class = form_class
124140
_meta.model = model
125141
_meta.return_field_name = return_field_name
@@ -132,7 +148,7 @@ def __init_subclass_with_meta__(cls, form_class=None, model=None, return_field_n
132148
input_fields,
133149
_as=InputField,
134150
)
135-
super(ModelFormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options)
151+
super(DjangoModelFormMutation, cls).__init_subclass_with_meta__(_meta=_meta, input_fields=input_fields, **options)
136152

137153
@classmethod
138154
def perform_mutate(cls, form, info):

graphene_django/forms/tests/test_mutation.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from py.test import raises
44

55
from graphene_django.tests.models import Pet, Film
6-
from ..mutation import FormMutation, ModelFormMutation
6+
from ..mutation import DjangoFormMutation, DjangoModelFormMutation
77

88

99
class MyForm(forms.Form):
@@ -19,22 +19,22 @@ class Meta:
1919

2020
def test_needs_form_class():
2121
with raises(Exception) as exc:
22-
class MyMutation(FormMutation):
22+
class MyMutation(DjangoFormMutation):
2323
pass
2424

2525
assert exc.value.args[0] == 'form_class is required for FormMutation'
2626

2727

2828
def test_has_output_fields():
29-
class MyMutation(FormMutation):
29+
class MyMutation(DjangoFormMutation):
3030
class Meta:
3131
form_class = MyForm
3232

3333
assert 'errors' in MyMutation._meta.fields
3434

3535

3636
def test_has_input_fields():
37-
class MyMutation(FormMutation):
37+
class MyMutation(DjangoFormMutation):
3838
class Meta:
3939
form_class = MyForm
4040

@@ -44,7 +44,7 @@ class Meta:
4444
class ModelFormMutationTests(TestCase):
4545

4646
def test_default_meta_fields(self):
47-
class PetMutation(ModelFormMutation):
47+
class PetMutation(DjangoModelFormMutation):
4848
class Meta:
4949
form_class = PetForm
5050

@@ -53,7 +53,7 @@ class Meta:
5353
self.assertIn('pet', PetMutation._meta.fields)
5454

5555
def test_custom_return_field_name(self):
56-
class PetMutation(ModelFormMutation):
56+
class PetMutation(DjangoModelFormMutation):
5757
class Meta:
5858
form_class = PetForm
5959
model = Film
@@ -64,19 +64,33 @@ class Meta:
6464
self.assertIn('animal', PetMutation._meta.fields)
6565

6666
def test_model_form_mutation_mutate(self):
67-
class PetMutation(ModelFormMutation):
67+
class PetMutation(DjangoModelFormMutation):
6868
class Meta:
6969
form_class = PetForm
7070

71-
result = PetMutation.mutate_and_get_payload(None, None, name='Fluffy')
71+
pet = Pet.objects.create(name='Axel')
72+
73+
result = PetMutation.mutate_and_get_payload(None, None, id=pet.pk, name='Mia')
74+
75+
self.assertEqual(Pet.objects.count(), 1)
76+
pet.refresh_from_db()
77+
self.assertEqual(pet.name, 'Mia')
78+
self.assertEqual(result.errors, [])
79+
80+
def test_model_form_mutation_updates_existing_(self):
81+
class PetMutation(DjangoModelFormMutation):
82+
class Meta:
83+
form_class = PetForm
84+
85+
result = PetMutation.mutate_and_get_payload(None, None, name='Mia')
7286

7387
self.assertEqual(Pet.objects.count(), 1)
7488
pet = Pet.objects.get()
75-
self.assertEqual(pet.name, 'Fluffy')
89+
self.assertEqual(pet.name, 'Mia')
7690
self.assertEqual(result.errors, [])
7791

7892
def test_model_form_mutation_mutate_invalid_form(self):
79-
class PetMutation(ModelFormMutation):
93+
class PetMutation(DjangoModelFormMutation):
8094
class Meta:
8195
form_class = PetForm
8296

0 commit comments

Comments
 (0)