prevPost
, nextPost
, commentList
필요!post
-> Post 모델에 관한 serializer 사용prevPost
, nextPost
: Post 모델에 관한 serializre를 사용하지만 'id'와 'title'만 가져오면 됨!commentList
: Comment 모델에 관한 serializer를 사용, List로 되어있으므로 many=True 인자를 주면 됨!serializers.py 수정 : PostSerializerDetail()
class PostSerializerSub(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'title']
class CommentSerializerSub(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ['id', 'content', 'update_dt']
# 일반 serializer 상속 -> 키(필드)를 직접 설정하는 경우
class PostSerializerDetail(serializers.Serializer):
post = PostRetrieveSerializer()
prevPost = PostSerializerSub() # id와 title만 가져옴
nextPost = PostSerializerSub() # id와 title만 가져옴
commentList = CommentSerializerSub(many=True) # 일부 필드만 사용하는 serializer('id', 'content', 'update_dt')
PostSerializerDetial
임 -> 그 안에 여러 개의 mini serializer들로 구성됨!(Nested Serializer)post = PostRetrieveSerializer()
: Post 모델의 전체 내용이 들어가야 하므로 PostRetrieveSerializer 사용prevPost = PostSerializerSub()
: Post 모델의 일부 필드('id', 'title')만 가져오는 PostSerializerSub 만들어서 사용 (nextPost도 동일!)commentList = CommentSerializerSub(many=True)
:views.py 수정 : PostRetrieveAPIView()
# get_xxx_by_update_dt 메서드 exception 처리 함수
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.DoesNotExit:
next_ = None
return prev, next_
# PostRetrieveAPIView 수정
class PostRetrieveAPIView(RetrieveAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializerDetail
# overriding
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
# prevInstance = instance.get_previous_by_update_dt() # update_dt를 기준으로 앞에 있는 인스턴스를 가져오는 메서드(built-in)
# nextInstance = instance.get_next_by_update_dt() # update_dt를 기준으로 뒤에 있는 인스턴스를 가져오는 메서드
prevInstance, nextInstance = get_prev_next(instance)
commentList = instance.comment_set.all() # 현재 post에 달려있는 comment 전부 가져오는 ORM 쿼리문
# 데이터를 준비해서 serializer type에 맞게 데이터를 공급해야 함!⭐⭐⭐
data = {
'post' : instance,
'prevPost' : prevInstance,
'nextPost' : nextInstance,
'commentList' : commentList,
}
serializer = self.get_serializer(instance=data) # 테이블에서 가져온 데이터를 serializer에 공급
return Response(serializer.data) # serializer.data 에서 '직렬화' 과정이 이루어짐! **
serializer_class = PostSerializerDetail
: 출력 결과는 PostSerializerDetail을 통해 보여줌(= PostSerializer로 직렬화!)
RetrieveAPIView를 오버라이딩하기 위해 소스 코드 살펴보기 (RetrieveAPIView > RetrieveModelMixin)
instance = self.get_object()
: 테이블로부터 인스턴스 가져옴serializer = self.get_serializer(instance)
: 가져온 데이터(인스턴스)를 serializer에 공급return Response(serializer.data)
: 직렬화된 데이터를 client instance.get_previous_by_update_dt()
: 'update_dt' 기준으로 앞에 있는 인스턴스를 가져오는 메서드 (Django 기본 제공)
instance.get_next_by_update_dt()
: 'update_dt' 기준으로 다음에 있는 인스턴스를 가져오는 메서드 (Django 기본 제공)
DateField
나 DateTimeField
이어야 함!(링크)commentList = instance.comment_set.all()
: 인스턴스(Post 객체)에 달려있는 comment_set을 전부 가져오는 메서드 (ForeignKey)
Browsable API
JSON
https://www.inflearn.com/course/%EC%9E%A5%EA%B3%A0-drf/dashboard