작성
·
284
0
# api2/urls.py router = routers.DefaultRouter() router.register(r'post', views.PostViewSet) urlpatterns = [ ... path('', include(router.urls)), ... ] # api2/views.py def get_prev_next(instance): try: prev = instance.get_previous_by_update_dt() except instance.DoesNotExist: prev = None try: next_ = instance.get_next_by_update_dt() except instance.DoesNotExist: next_ = None return prev, next_ class PostViewSet(ModelViewSet): queryset = Post.objects.all() serializer_class = PostListSerializer pagination_class = PostPageNumberPagination def get_serializer_context(self): return { 'request': None, 'format': self.format_kwarg, 'view': self } def get_queryset(self): return Post.objects.all().select_related('category').prefetch_related('tags', 'comment_set') def retrieve(self, request, *args, **kwargs): instance = self.get_object() prevInstance, nextInstance = get_prev_next(instance) commentList = instance.comment_set.all() data = { 'post': instance, 'prevPost': prevInstance, 'nextPost': nextInstance, 'commentList': commentList, } serializer = PostSerializerDetail(instance=data) return Response(serializer.data)
path('post/', views.PostViewSet.as_view(actions={
'get': 'list',
}), name='post-list'),
path('post/<int:pk>/', views.PostViewSet.as_view(actions={
'get': 'retrieve',
}), name='post-detail'),
path('post/<int:pk>/like/', views.PostViewSet.as_view(actions={
'get': 'like',
}), name='post-like'),
답변 2
1
/api2/post/2/?format=json 으로 해 볼래요. 그 차이를 알 수 있을 것입니다.
이 처리과정이 기본 로직이고,
질문 내용은, /api2/post/2/ 에 대한 응답으로 Browsable API 화면을 만드는 과정에서,
PUT/PATCH 용 폼을 보여주기 위해서, get_serializer_class() 를 호출하는 것입니다.
이 폼을 처리하는 로직은 알면 좋겠지만 그리 중요해 보이지는 않습니다만...
즉 일반적인 시리얼라이저 로직 플로우는 아닌 것 입니다.
참고하세요.
1
안녕하세요. 독자님.
에러가 나는 원인은, list/retrieve 처리에 시리얼라이저가 다르고,
상단에 있는 serializer_class=PostListSerializer 가 디폴트 시리얼라이저로 작동하기 때문입니다.
상단의 serializer_class 라인을 삭제하고, 아래 내용을 추가해 보세요.
def get_serializer_class(self):
if self.action == 'list':
return PostListSerializer
if self.action == 'retrieve':
return PostSerializerDetail
return PostSerializerDetail
감사합니다! 그렇게 하니까 해결이 되네요.
그런데 주신 코드를 아래와 같이 수정하면 get_serializer_class가 총 4회에 걸쳐 실행되고, 처음 액션은 retrieve, 그 이후에는 각각 update, partial_update, update로 찍히는데요 혹시
1)어디에서 get_serializer_class가 호출되는지,
2)왜 액션이 update와 partail_update인지 설명해주실 수 있으신지요^^??
제가 작성한 코드
class PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostListSerializer
pagination_class = PostPageNumberPagination
def get_serializer_class(self):
if self.action == 'list':
print(self.action, 111)
return PostListSerializer
if self.action == 'retrieve':
print(self.action, 222)
return PostSerializerDetail
print(self.action, 333)
return PostSerializerDetail
def update(self, request, *args, **kwargs):
print("update working")
return super().update(request, *args, **kwargs)
def partial_update(self, request, *args, **kwargs):
print("partial working")
return super().partial_update(request, *args, **kwargs)
def get_queryset(self):
return Post.objects.all().select_related('category').prefetch_related('tags', 'comment_set')
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
prevInstance, nextInstance = get_prev_next(instance)
commentList = instance.comment_set.all()
data = {
'post': instance,
'prevPost': prevInstance,
'nextPost': nextInstance,
'commentList': commentList,
}
serializer = self.get_serializer(instance=data)
return Response(serializer.data)
def get_serializer_context(self):
return {
'request': None,
'format': self.format_kwarg,
'view': self
}
def like(self, request, *args, **kwargs):
instance = self.get_object()
instance.like += 1
instance.save()
return Response(instance.like)
코드가 실행되었을 때 찍힌 로그
retrieve working
retrieve 222
update 333
partial_update 333
update 333
이 부분도 수정이 필요하네요.