Skip to content

Commit dccfa91

Browse files
committed
fix: NestedModelSerializer source 매핑 및 mixed-list create-during-update 지원
1 parent 071740b commit dccfa91

1 file changed

Lines changed: 16 additions & 10 deletions

File tree

app/core/serializer/nested_model_serializer.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@ def to_internal_value(self, data: list[dict]) -> list[dict]:
6060
data = self._validate_data(data)
6161
ret, errors = [], []
6262

63+
# self.instance 가 명시적으로 set 된 경우(예: instance=tags) length 가 _validate_data 에서 검증됨 →
64+
# id 미지정 시 위치 기반 매칭이 안전. parent 에서 fetch 한 경우는 length 검증 없으므로 위치 매칭 금지.
65+
has_explicit_instance = self.instance is not None
6366
child_instances = self.instance or (
64-
self.parent and self.parent.instance and getattr(self.parent.instance, self.field_name)
67+
self.parent and self.parent.instance and getattr(self.parent.instance, self.source or self.field_name)
6568
)
6669
if isinstance(child_instances, BaseManager):
6770
child_instances = list(child_instances.all())
@@ -70,14 +73,15 @@ def to_internal_value(self, data: list[dict]) -> list[dict]:
7073
try:
7174
self.child.initial_data = item
7275
self.child.context["index"] = index
73-
if child_instances:
74-
if "id" in item:
75-
target_instance = next((i for i in child_instances if str(i.id) == str(item["id"])), None)
76-
if not target_instance:
77-
raise serializers.ValidationError("유효하지 않은 ID입니다.", code="not_found")
78-
self.child.instance = target_instance
79-
else:
80-
self.child.instance = child_instances[index]
76+
# 매 iteration 마다 초기화 — id 없는 항목은 create 모드로 검증.
77+
self.child.instance = None
78+
if child_instances and "id" in item:
79+
target_instance = next((i for i in child_instances if str(i.id) == str(item["id"])), None)
80+
if not target_instance:
81+
raise serializers.ValidationError("유효하지 않은 ID입니다.", code="not_found")
82+
self.child.instance = target_instance
83+
elif child_instances and has_explicit_instance:
84+
self.child.instance = child_instances[index]
8185
validated = self.run_child_validation(item)
8286
except serializers.ValidationError as exc:
8387
errors.append(exc.detail)
@@ -103,7 +107,9 @@ def _update_child_instance(self, serializer_obj: serializers.BaseSerializer, ins
103107
child_serializer.save()
104108

105109
def _update_list_instances(self, field: serializers.ListSerializer, data: list[dict]) -> None:
106-
if (instances := getattr(self.instance, field.field_name)) and isinstance(instances, BaseManager):
110+
if (instances := getattr(self.instance, field.source or field.field_name)) and isinstance(
111+
instances, BaseManager
112+
):
107113
instances = list(instances.all())
108114

109115
instance_dict = {str(i.pk): i for i in instances}

0 commit comments

Comments
 (0)