Skip to content

Commit 1281c13

Browse files
authored
Introduced optional_fields to SerializationMutation (#1080)
* added optional_field to SerializationMutation to forcefully mark some fields as optional * added tests
1 parent caf9548 commit 1281c13

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

graphene_django/rest_framework/mutation.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class SerializerMutationOptions(MutationOptions):
1818
model_class = None
1919
model_operations = ["create", "update"]
2020
serializer_class = None
21+
optional_fields = ()
2122

2223

2324
def fields_for_serializer(
@@ -27,6 +28,7 @@ def fields_for_serializer(
2728
is_input=False,
2829
convert_choices_to_enum=True,
2930
lookup_field=None,
31+
optional_fields=(),
3032
):
3133
fields = OrderedDict()
3234
for name, field in serializer.fields.items():
@@ -44,9 +46,13 @@ def fields_for_serializer(
4446

4547
if is_not_in_only or is_excluded:
4648
continue
49+
is_optional = name in optional_fields
4750

4851
fields[name] = convert_serializer_field(
49-
field, is_input=is_input, convert_choices_to_enum=convert_choices_to_enum
52+
field,
53+
is_input=is_input,
54+
convert_choices_to_enum=convert_choices_to_enum,
55+
force_optional=is_optional,
5056
)
5157
return fields
5258

@@ -70,6 +76,7 @@ def __init_subclass_with_meta__(
7076
exclude_fields=(),
7177
convert_choices_to_enum=True,
7278
_meta=None,
79+
optional_fields=(),
7380
**options
7481
):
7582

@@ -95,6 +102,7 @@ def __init_subclass_with_meta__(
95102
is_input=True,
96103
convert_choices_to_enum=convert_choices_to_enum,
97104
lookup_field=lookup_field,
105+
optional_fields=optional_fields,
98106
)
99107
output_fields = fields_for_serializer(
100108
serializer,

graphene_django/rest_framework/serializer_converter.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ def get_graphene_type_from_serializer_field(field):
1919
)
2020

2121

22-
def convert_serializer_field(field, is_input=True, convert_choices_to_enum=True):
22+
def convert_serializer_field(
23+
field, is_input=True, convert_choices_to_enum=True, force_optional=False
24+
):
2325
"""
2426
Converts a django rest frameworks field to a graphql field
2527
and marks the field as required if we are creating an input type
@@ -32,7 +34,10 @@ def convert_serializer_field(field, is_input=True, convert_choices_to_enum=True)
3234
graphql_type = get_graphene_type_from_serializer_field(field)
3335

3436
args = []
35-
kwargs = {"description": field.help_text, "required": is_input and field.required}
37+
kwargs = {
38+
"description": field.help_text,
39+
"required": is_input and field.required and not force_optional,
40+
}
3641

3742
# if it is a tuple or a list it means that we are returning
3843
# the graphql type and the child type

graphene_django/rest_framework/tests/test_mutation.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from py.test import raises
44
from rest_framework import serializers
55

6-
from graphene import Field, ResolveInfo
6+
from graphene import Field, ResolveInfo, NonNull, String
77
from graphene.types.inputobjecttype import InputObjectType
88

99
from ...types import DjangoObjectType
@@ -98,6 +98,25 @@ class Meta:
9898
assert "created" not in MyMutation.Input._meta.fields
9999

100100

101+
def test_model_serializer_required_fields():
102+
class MyMutation(SerializerMutation):
103+
class Meta:
104+
serializer_class = MyModelSerializer
105+
106+
assert "cool_name" in MyMutation.Input._meta.fields
107+
assert MyMutation.Input._meta.fields["cool_name"].type == NonNull(String)
108+
109+
110+
def test_model_serializer_optional_fields():
111+
class MyMutation(SerializerMutation):
112+
class Meta:
113+
serializer_class = MyModelSerializer
114+
optional_fields = ("cool_name",)
115+
116+
assert "cool_name" in MyMutation.Input._meta.fields
117+
assert MyMutation.Input._meta.fields["cool_name"].type == String
118+
119+
101120
def test_write_only_field():
102121
class WriteOnlyFieldModelSerializer(serializers.ModelSerializer):
103122
password = serializers.CharField(write_only=True)

0 commit comments

Comments
 (0)