Skip to content

Commit e49a01c

Browse files
adding optional_field in Serializermutation to enfore some fields to be optional (#1455)
* adding optional_fields to enforce fields to be optional * adding support for all * adding unit tests * Update graphene_django/rest_framework/mutation.py Co-authored-by: Kien Dang <kiend@pm.me> * linting * linting * add missing import --------- Co-authored-by: Kien Dang <kiend@pm.me>
1 parent 0473f1a commit e49a01c

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

graphene_django/rest_framework/mutation.py

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

2324

2425
def fields_for_serializer(
@@ -28,6 +29,7 @@ def fields_for_serializer(
2829
is_input=False,
2930
convert_choices_to_enum=True,
3031
lookup_field=None,
32+
optional_fields=(),
3133
):
3234
fields = OrderedDict()
3335
for name, field in serializer.fields.items():
@@ -48,9 +50,13 @@ def fields_for_serializer(
4850

4951
if is_not_in_only or is_excluded:
5052
continue
53+
is_optional = name in optional_fields or "__all__" in optional_fields
5154

5255
fields[name] = convert_serializer_field(
53-
field, is_input=is_input, convert_choices_to_enum=convert_choices_to_enum
56+
field,
57+
is_input=is_input,
58+
convert_choices_to_enum=convert_choices_to_enum,
59+
force_optional=is_optional,
5460
)
5561
return fields
5662

@@ -74,6 +80,7 @@ def __init_subclass_with_meta__(
7480
exclude_fields=(),
7581
convert_choices_to_enum=True,
7682
_meta=None,
83+
optional_fields=(),
7784
**options
7885
):
7986
if not serializer_class:
@@ -98,6 +105,7 @@ def __init_subclass_with_meta__(
98105
is_input=True,
99106
convert_choices_to_enum=convert_choices_to_enum,
100107
lookup_field=lookup_field,
108+
optional_fields=optional_fields,
101109
)
102110
output_fields = fields_for_serializer(
103111
serializer,

graphene_django/rest_framework/serializer_converter.py

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

2020

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

3335
args = []
34-
kwargs = {"description": field.help_text, "required": is_input and field.required}
36+
kwargs = {
37+
"description": field.help_text,
38+
"required": is_input and field.required and not force_optional,
39+
}
3540

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

graphene_django/rest_framework/tests/test_mutation.py

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

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

99
from ...types import DjangoObjectType
@@ -105,6 +105,16 @@ class Meta:
105105
assert "created" not in MyMutation.Input._meta.fields
106106

107107

108+
def test_model_serializer_optional_fields():
109+
class MyMutation(SerializerMutation):
110+
class Meta:
111+
serializer_class = MyModelSerializer
112+
optional_fields = ("cool_name",)
113+
114+
assert "cool_name" in MyMutation.Input._meta.fields
115+
assert MyMutation.Input._meta.fields["cool_name"].type == String
116+
117+
108118
def test_write_only_field():
109119
class WriteOnlyFieldModelSerializer(serializers.ModelSerializer):
110120
password = serializers.CharField(write_only=True)

0 commit comments

Comments
 (0)