Skip to content

Commit 45d48c4

Browse files
authored
fix(input): use None as default for Maybe fields instead of UNSET (#824)
1 parent 49776a2 commit 45d48c4

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

strawberry_django/type.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from strawberry.types.base import WithStrawberryObjectDefinition
2828
from strawberry.types.cast import get_strawberry_type_cast
2929
from strawberry.types.field import StrawberryField
30+
from strawberry.types.maybe import _annotation_is_maybe # noqa: PLC2701
3031
from strawberry.types.private import is_private
3132
from strawberry.utils.deprecations import DeprecatedDescriptor
3233
from typing_extensions import Self, dataclass_transform, get_annotations
@@ -165,18 +166,22 @@ def _process_type(
165166
# FIXME: For input types it is important to set the default value to UNSET
166167
# Is there a better way of doing this?
167168
if is_input:
169+
# For Maybe types, the default should be None (matching strawberry's behavior)
170+
# For other types, the default should be UNSET
171+
is_maybe = _annotation_is_maybe(annotation)
172+
default_value = None if is_maybe else UNSET
173+
168174
# First check if the field is defined in the class. If it is,
169-
# then we just need to set its default value to UNSET in case
170-
# it is MISSING
175+
# then we just need to set its default value in case it is MISSING
171176
if field_name in cls.__dict__:
172177
field = cls.__dict__[field_name]
173178
if (
174179
isinstance(field, dataclasses.Field)
175180
and field.default is dataclasses.MISSING
176181
):
177-
field.default = UNSET
182+
field.default = default_value
178183
if isinstance(field, StrawberryField):
179-
field.default_value = UNSET
184+
field.default_value = default_value
180185

181186
continue
182187

@@ -185,12 +190,12 @@ def _process_type(
185190
if base_field is not None and isinstance(base_field, StrawberryField):
186191
new_field = copy.copy(base_field)
187192
else:
188-
new_field = _field(default=UNSET)
193+
new_field = _field(default=default_value)
189194

190195
cls_annotations[field_name] = field_annotation.raw_annotation
191-
new_field.default = UNSET
196+
new_field.default = default_value
192197
if isinstance(base_field, StrawberryField):
193-
new_field.default_value = UNSET
198+
new_field.default_value = default_value
194199

195200
setattr(cls, field_name, new_field)
196201

tests/types2/test_input.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import dataclasses
12
from typing import cast
23

34
import strawberry
45
from strawberry import auto
56
from strawberry.types import get_object_definition
67
from strawberry.types.base import StrawberryOptional
8+
from strawberry.types.maybe import Maybe
79

810
import strawberry_django
911

@@ -113,3 +115,27 @@ class Input(Base):
113115
),
114116
("another_name", StrawberryOptional(strawberry_django.OneToManyInput)),
115117
]
118+
119+
120+
def test_maybe_field_default_value():
121+
@strawberry_django.input(TypeModel)
122+
class InputWithMaybe:
123+
my_maybe_field: Maybe[bool]
124+
regular_optional_field: str | None
125+
126+
@strawberry.input
127+
class StrawberryInputWithMaybe:
128+
my_maybe_field: Maybe[bool]
129+
130+
django_fields = {f.name: f for f in dataclasses.fields(InputWithMaybe)}
131+
strawberry_fields = {
132+
f.name: f for f in dataclasses.fields(StrawberryInputWithMaybe)
133+
}
134+
135+
assert django_fields["my_maybe_field"].default is None
136+
assert (
137+
django_fields["my_maybe_field"].default
138+
== strawberry_fields["my_maybe_field"].default
139+
)
140+
141+
assert django_fields["regular_optional_field"].default is strawberry.UNSET

0 commit comments

Comments
 (0)