[DRF] 좋아요 기능2 - GET 메서드 사용

Jinhyung Rhee·2022년 8월 14일
0

좋아요 기능

  • /api/like/99/ : GET 메서드
  • /api2/post/99/like/ : PATCH 메서드
  • 특징
    • 사용자가 입력하는 데이터가 없음
    • ex) 사용자가 click만하면 like 컬럼이 1 증가하는 기능

Serializer의 두 가지 모드(Read/Write)

  • Read(직렬화)
    • GET 요청
    • 흐름 : instance → dict → bytes
  • Write(역직렬화)
    • POST, PUT, PATCH, DELETE 요청
    • 흐름 : bytes → dict → is_valid() → instance
  • 좋아요 기능은 사용자로부터 입력받는 값이 없기 때문에, bytes → dict → is_valid() 까지의 역직렬화 과정이 불필요함!
  • 따라서, 좋아요 기능은 굳이 PATCH 메서드로 처리하지 않고 GET 메서드로 처리도 가능함!

PATCH 메서드로 구현된 좋아요 기능을 GET 메서드로 받도록 변경하기

  • PATCH 메서드로 구현된 좋아요 기능(views.py)

    class PostLikeAPIView(UpdateAPIView):
      queryset = Post.objects.all()
      serializer_class = PostLikeSerializer
    
      # PATCH method
      # update 메서드 오버라이딩
      def update(self, request, *args, **kwargs):
            partial = kwargs.pop('partial', False)
            instance = self.get_object()
            # 내부에 like + 1 로직 추가 (이후 serializer의 data변수에 dict 형태로 넣어줌)
            data = {'like' : instance.like + 1}
            # data = instance.like + 1
            serializer = self.get_serializer(instance, data=data, partial=partial)
            serializer.is_valid(raise_exception=True)
            self.perform_update(serializer)
    
            if getattr(instance, '_prefetched_objects_cache', None):
                # If 'prefetch_related' has been applied to a queryset, we need to
                # forcibly invalidate the prefetch cache on the instance.
                instance._prefetched_objects_cache = {}
    
            # return Response(serializer.data)
            return Response(data['like'])
  • GET 메서드로 구현된 좋아요 기능(views.py) → serializer 클래스 사용 X

    class PostLikeAPIView(GenericAPIView):
      queryset = Post.objects.all()
      # serializer_class = PostLikeSerializer
    
      # GET method (역직렬화 과정 불필요)**
      def get(self, request, *args, **kwargs):
            instance = self.get_object()
            instance.like += 1
            instance.save()
    
            return Response(instance.like)
    • instance = self.get_object() : DB로부터 instance를 가져옴

    • instance.like += 1 : like 속성을 1 증가시킴

    • instance.save() : 변경된 instance를 DB에 저장

    • return Response(instance.like) : 새로운 like 값(instance.like)을 client에게 보내줌

    • serializer 클래스는 사용하지 않아서 주석처리 해주었는데, queryset은 여전히 필요한지 확인해보기!⭐

      • get_object() + ctrl + click → GenericAPIView 클래스에 정의

        • 내부에서 get_queryset() 메서드를 호출하고 있음!
      • get_queryset() + ctrl + click → GenericAPIView 클래스에 정의

        • self.queryset 속성이 없으면 에러가 나도록 처리하고 있음! (assert ~ )
      • 이 두 메서드(get_object()get_queryset())은 GenericAPIView 클래스에 정의되어 있음!

      • 코드에서 get_object()get_queryset() 메서드를 사용하려면 APIView가 아니라 GenericAPIView를 상속받아야 함!⭐

      • 동일한 기능을 APIView를 상속받아 구현할 수도 있지만 '재사용성' 측면에서 권장하지는 않음

        # GenericAPIView대신 APIView를 상속받아 사용
        class PostLikeAPIView(APIView):
         # queryset = Post.objects.all()
         # serializer_class = PostLikeSerializer
        
         # GET method (역직렬화 과정 불필요)**
         def get(self, request, *args, **kwargs):
               # instance = self.get_object(~)
               instance = get_object_or_404()
               instance.like += 1
               instance.save()
        
           return Response(instance.like)
        • APIView를 상속받아 사용하면, 'queryset'이나 'get_object()' 메서드를 사용하지 않고 get_object_or_404(~)로 DB에서 instance를 가져오는 코드를 직접 작성해야 함!
        • 이를 권장하지 않는 이유
          • '기존 코드가 존재하면 재활용한다'는 파이썬의 원칙에 부합하지 않음
          • 코드를 재활용하는 것이 에러의 가능성을 줄여주는 방법이기 때문

결과

  • 초기 좋아요 개수 : 8개

  • GET /api2/post/4/like/ 요청보내기

Reference

https://www.inflearn.com/course/%EC%9E%A5%EA%B3%A0-drf/dashboard

profile
기록하는 습관

0개의 댓글