Skip to content

Commit 2fea545

Browse files
committed
fix: 2025년 행사가 retrieve되지 않던 문제 수정
1 parent b0ad792 commit 2fea545

4 files changed

Lines changed: 46 additions & 2 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from django.db.models.query import QuerySet
2+
from rest_framework import viewsets
3+
4+
5+
class ListOnlyFilterMixin(viewsets.GenericViewSet):
6+
"""목록용 필터를 list action 에만 적용한다.
7+
8+
DRF 의 get_object() 는 filter_queryset() 을 거치므로, 목록 기본 스코프
9+
(EventFilterMixin 의 "최신 이벤트" 등)가 단건 조회까지 좁혀 PK 가 유효한데도
10+
404 가 난다. 단건 조회는 PK 로 지목하는 영구 링크이므로 스코프 밖이어도 접근 가능해야 한다.
11+
"""
12+
13+
def filter_queryset(self, queryset: QuerySet) -> QuerySet:
14+
if self.action != "list":
15+
return queryset
16+
17+
return super().filter_queryset(queryset)

app/event/presentation/test/api_test.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ def test_presentation_defaults_to_latest_event(api_client: APIClient):
8989
assert response_data[0]["id"] == str(new_prst.id)
9090

9191

92+
@pytest.mark.django_db
93+
def test_presentation_retrieve_ignores_latest_event_default(api_client: APIClient):
94+
# Given: 지난 행사의 발표가 있고, 그보다 최신인 행사가 존재함.
95+
organization = Organization.objects.create(name="Test Organization")
96+
old_event = Event.objects.create(
97+
organization=organization, name="PyCon Korea 2025", event_start_at=datetime(2025, 8, 1)
98+
)
99+
Event.objects.create(organization=organization, name="PyCon Korea 2026", event_start_at=datetime(2026, 8, 1))
100+
101+
old_type = PresentationType.objects.create(event=old_event, name="Talk")
102+
old_prst = Presentation.objects.create(type=old_type, title="Old Presentation")
103+
104+
# When: event 파라미터 없이 지난 행사의 발표를 단건 조회
105+
response = api_client.get(reverse("v1:presentation-detail", kwargs={"pk": old_prst.id}))
106+
107+
# Then: 목록 기본 스코프(최신 행사)와 무관하게 조회된다.
108+
assert response.status_code == http.HTTPStatus.OK
109+
assert response.json()["id"] == str(old_prst.id)
110+
111+
92112
def _make_public_file(name: str) -> PublicFile:
93113
return PublicFile.objects.create(file=f"public/{name}.png", mimetype="image/png", hash=name, size=0)
94114

app/event/presentation/views.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from core.const.tag import OpenAPITag
2+
from core.viewset.list_only_filter_viewset import ListOnlyFilterMixin
23
from django.db.models.query import QuerySet
34
from django.shortcuts import get_object_or_404
45
from django.utils.decorators import method_decorator
@@ -28,7 +29,12 @@ class PresentationCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet
2829

2930
@method_decorator(name="list", decorator=extend_schema(tags=[OpenAPITag.EVENT_PRESENTATION]))
3031
@method_decorator(name="retrieve", decorator=extend_schema(tags=[OpenAPITag.EVENT_PRESENTATION]))
31-
class PresentationViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
32+
class PresentationViewSet(
33+
ListOnlyFilterMixin,
34+
mixins.ListModelMixin,
35+
mixins.RetrieveModelMixin,
36+
viewsets.GenericViewSet,
37+
):
3238
queryset = Presentation.objects.get_all_nested_data()
3339
serializer_class = PresentationSerializer
3440
filterset_class = PresentationFilterSet

app/event/sponsor/views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from core.const.tag import OpenAPITag
2+
from core.viewset.list_only_filter_viewset import ListOnlyFilterMixin
23
from django.db import models
34
from django.utils.decorators import method_decorator
45
from drf_spectacular.utils import extend_schema
@@ -9,7 +10,7 @@
910

1011

1112
@method_decorator(name="list", decorator=extend_schema(tags=[OpenAPITag.EVENT_SPONSOR]))
12-
class SponsorTierViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
13+
class SponsorTierViewSet(ListOnlyFilterMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
1314
queryset = SponsorTier.objects.filter_active().prefetch_related(
1415
models.Prefetch(
1516
lookup="sponsors",

0 commit comments

Comments
 (0)