Skip to content

Commit c1f3311

Browse files
committed
fix: API가 정상 응답을 할 수 있도록 수정
1 parent cf821a1 commit c1f3311

File tree

5 files changed

+92
-19
lines changed

5 files changed

+92
-19
lines changed

app/admin_api/serializers/event/presentation.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from admin_api.serializers.modification_audit import ModificationAuditResponseAdminSerializer
12
from core.const.serializer import COMMON_ADMIN_FIELDS
23
from core.serializer.base_abstract_serializer import BaseAbstractSerializer
34
from core.serializer.json_schema_serializer import JsonSchemaSerializer
45
from event.presentation.models import Presentation, PresentationCategory, PresentationSpeaker, PresentationType
56
from file.models import PublicFile
7+
from participant_portal_api.models import ModificationAudit
68
from rest_framework import serializers
79
from user.models import UserExt
810

@@ -61,3 +63,49 @@ class PresentationSpeakerAdminSerializer(BaseAbstractSerializer, JsonSchemaSeria
6163
class Meta:
6264
model = PresentationSpeaker
6365
fields = COMMON_ADMIN_FIELDS + ("presentation", "user", "image", "biography_ko", "biography_en")
66+
67+
68+
class PresentationModificationAuditPreviewAdminSerializer(serializers.ModelSerializer):
69+
class PresentationSerializer(serializers.ModelSerializer):
70+
class PresentationSpeakerSerializer(serializers.ModelSerializer):
71+
class UserSerializer(serializers.ModelSerializer):
72+
class Meta:
73+
model = UserExt
74+
fields = ("id", "nickname_ko", "nickname_en")
75+
76+
user = UserSerializer(read_only=True)
77+
image = serializers.FileField(read_only=True, allow_null=True, source="image.file")
78+
79+
class Meta:
80+
model = PresentationSpeaker
81+
fields = ("id", "user", "image", "biography_ko", "biography_en")
82+
83+
type = serializers.CharField(read_only=True, source="type.name_ko")
84+
categories = serializers.SerializerMethodField(read_only=True)
85+
speakers = PresentationSpeakerSerializer(read_only=True, many=True)
86+
87+
class Meta:
88+
model = Presentation
89+
fields = (
90+
"type",
91+
"categories",
92+
"image",
93+
"title_ko",
94+
"title_en",
95+
"summary_ko",
96+
"summary_en",
97+
"description_ko",
98+
"description_en",
99+
"speakers",
100+
)
101+
102+
def get_categories(self, obj: Presentation) -> list[str]:
103+
return [cat.name_ko for cat in obj.categories]
104+
105+
modification_audit = ModificationAuditResponseAdminSerializer(source="*")
106+
original = PresentationSerializer(source="fake_original_instance")
107+
modified = PresentationSerializer(source="fake_modified_instance")
108+
109+
class Meta:
110+
model = ModificationAudit
111+
fields = ("modification_audit", "original", "modified")

app/admin_api/serializers/user.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import functools
22
import typing
33

4+
from admin_api.serializers.modification_audit import ModificationAuditResponseAdminSerializer
45
from core.const.serializer import COMMON_ADMIN_FIELDS
56
from core.serializer.base_abstract_serializer import BaseAbstractSerializer
67
from core.serializer.json_schema_serializer import JsonSchemaSerializer
78
from core.serializer.read_only_serializer import ReadOnlyModelSerializer
9+
from participant_portal_api.models import ModificationAudit
810
from rest_framework import serializers
911
from user.models import UserExt
1012
from user.models.organization import Organization
@@ -35,6 +37,27 @@ class Meta:
3537
}
3638

3739

40+
class UserModificationAuditPreviewAdminSerializer(serializers.ModelSerializer):
41+
class UserSerializer(serializers.ModelSerializer):
42+
image = serializers.SerializerMethodField()
43+
44+
class Meta:
45+
model = UserExt
46+
fields = ("id", "image", "email", "nickname_ko", "nickname_en")
47+
48+
def get_image(self, obj: UserExt) -> str | None:
49+
# I don't know why, but serializers.FileField(source="image.file") does not work here.
50+
return obj.image.file if obj.image else None
51+
52+
modification_audit = ModificationAuditResponseAdminSerializer(source="*")
53+
original = UserSerializer(source="fake_original_instance")
54+
modified = UserSerializer(source="fake_modified_instance")
55+
56+
class Meta:
57+
model = ModificationAudit
58+
fields = ("modification_audit", "original", "modified")
59+
60+
3861
class UserAdminSignInSerializerData(typing.TypedDict):
3962
identity: str
4063
password: str

app/admin_api/views/event/presentation.py

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from admin_api.serializers.event.presentation import (
99
PresentationAdminSerializer,
1010
PresentationCategoryAdminSerializer,
11+
PresentationModificationAuditPreviewAdminSerializer,
1112
PresentationSpeakerAdminSerializer,
1213
PresentationTypeAdminSerializer,
1314
)
@@ -53,7 +54,10 @@ class PresentationAdminViewSet(JsonSchemaViewSet, viewsets.ModelViewSet):
5354
filterset_class = PresentationAdminFilterSet
5455
queryset = Presentation.objects.get_all_nested_data().select_related("created_by", "updated_by", "deleted_by")
5556

56-
@extend_schema(tags=[OpenAPITag.ADMIN_EVENT_PRESENTATION])
57+
@extend_schema(
58+
tags=[OpenAPITag.ADMIN_EVENT_PRESENTATION],
59+
responses={status.HTTP_200_OK: PresentationModificationAuditPreviewAdminSerializer},
60+
)
5761
@decorators.action(detail=True, methods=["get"], url_path=r"preview/(?P<audit_id>[\w-]+)")
5862
def preview_modification_audit(
5963
self, request: request.Request, audit_id: str, *args: tuple, **kwargs: dict
@@ -64,7 +68,7 @@ def preview_modification_audit(
6468
if not (audit := ModificationAudit.objects.filter_by_instance(self.get_object()).filter(id=audit_id).first()):
6569
return response.Response(status=status.HTTP_404_NOT_FOUND)
6670

67-
return response.Response(data=audit.get_applied_data(serializer_class=self.get_serializer_class()))
71+
return response.Response(data=PresentationModificationAuditPreviewAdminSerializer(instance=audit).data)
6872

6973

7074
@extend_schema_view(**{m: extend_schema(tags=[OpenAPITag.ADMIN_EVENT_PRESENTATION]) for m in ADMIN_METHODS})
@@ -74,16 +78,3 @@ class PresentationSpeakerAdminViewSet(JsonSchemaViewSet, viewsets.ModelViewSet):
7478
permission_classes = [IsSuperUser]
7579
filterset_class = PresentationSpeakerAdminFilterSet
7680
queryset = PresentationSpeaker.objects.filter_active().select_related("created_by", "updated_by", "deleted_by")
77-
78-
@extend_schema(tags=[OpenAPITag.ADMIN_EVENT_PRESENTATION])
79-
@decorators.action(detail=True, methods=["get"], url_path=r"preview/(?P<audit_id>[\w-]+)")
80-
def preview_modification_audit(
81-
self, request: request.Request, audit_id: str, *args: tuple, **kwargs: dict
82-
) -> response.Response:
83-
if not UUID_V4_REGEX.match(audit_id):
84-
return response.Response(status=status.HTTP_404_NOT_FOUND)
85-
86-
if not (audit := ModificationAudit.objects.filter_by_instance(self.get_object()).filter(id=audit_id).first()):
87-
return response.Response(status=status.HTTP_404_NOT_FOUND)
88-
89-
return response.Response(data=audit.get_applied_data(serializer_class=self.get_serializer_class()))

app/admin_api/views/user.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
UserAdminPasswordChangeSerializer,
44
UserAdminSerializer,
55
UserAdminSignInSerializer,
6+
UserModificationAuditPreviewAdminSerializer,
67
)
78
from core.const.account import INITIAL_ADMIN_PASSWORD
89
from core.const.regex import UUID_V4_REGEX
@@ -80,7 +81,10 @@ def change_password(self, request: request.Request, *args: tuple, **kwargs: dict
8081
serializer.save()
8182
return response.Response(data=UserAdminSerializer(serializer.instance).data)
8283

83-
@extend_schema(tags=[OpenAPITag.ADMIN_USER])
84+
@extend_schema(
85+
tags=[OpenAPITag.ADMIN_USER],
86+
responses={status.HTTP_200_OK: UserModificationAuditPreviewAdminSerializer},
87+
)
8488
@decorators.action(detail=True, methods=["get"], url_path=r"preview/(?P<audit_id>[\w-]+)")
8589
def preview_modification_audit(
8690
self, request: request.Request, audit_id: str, *args: tuple, **kwargs: dict
@@ -91,7 +95,7 @@ def preview_modification_audit(
9195
if not (audit := ModificationAudit.objects.filter_by_instance(self.get_object()).filter(id=audit_id).first()):
9296
return response.Response(status=status.HTTP_404_NOT_FOUND)
9397

94-
return response.Response(data=audit.get_applied_data(serializer_class=self.get_serializer_class()))
98+
return response.Response(data=UserModificationAuditPreviewAdminSerializer(instance=audit).data)
9599

96100

97101
@extend_schema_view(**{m: extend_schema(tags=[OpenAPITag.ADMIN_USER]) for m in ADMIN_METHODS})

app/core/util/django_orm.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,21 @@ def json_to_simplenamespace(model_data: dict[str, dict[str, typing.Any]], key: s
228228
if is_identifier(attr_value):
229229
if not (resolved_instance := resolved_models.get(attr_value)):
230230
resolved_instance = identifier_to_model(attr_value)
231+
if not resolved_instance:
232+
raise ValueError(f"Foreign model not found for identifier: {attr_value}")
231233
setattr(resolved_model, attr_name, resolved_instance)
232-
elif isinstance(attr_value, list) and all(is_identifier(item) for item in attr_value):
234+
elif (
235+
isinstance(attr_value, collections.abc.Iterable)
236+
and attr_value
237+
and all(is_identifier(item) for item in attr_value)
238+
):
233239
resolved_many_rel_models = []
234240
for item in attr_value:
235241
if not (resolved_instance := resolved_models.get(item)):
236242
resolved_instance = identifier_to_model(item)
237243
if not resolved_instance:
238244
raise ValueError(f"Related model not found for identifier: {item}")
245+
resolved_many_rel_models.append(resolved_instance)
239246

240247
setattr(resolved_model, attr_name, resolved_many_rel_models)
241248

@@ -256,7 +263,7 @@ def apply_diff_to_model(models_data: dict[str, dict[str, typing.Any]]) -> list[m
256263
if not (related_model_instance := identifier_to_model(value)):
257264
raise ValueError(f"Related model not found for identifier: {value}")
258265
setattr(model_instance, field_name, related_model_instance)
259-
elif isinstance(value, list) and all(is_identifier(item) for item in value):
266+
elif isinstance(value, collections.abc.Iterable) and value and all(is_identifier(item) for item in value):
260267
# If the value is a list of model identifiers, resolve them to model instances
261268
related_model_instances = [identifier_to_model(item) for item in value]
262269
if None in related_model_instances:

0 commit comments

Comments
 (0)