[DRF] ViewSet vs Generic Views

Jinhyung Rhee·2022년 8월 10일
0

ViewSet을 사용하여 user, post, comment 기능 구현

  • urls.py

    from django.urls import path, include
    from rest_framework import routers
    from .views import UserViewSet, PostViewSet, CommentViewSet
    
    router = routers.DefaultRouter()
    router.register(r'user', UserViewSet)
    router.register(r'post', PostViewSet)
    router.register(r'comment', CommentViewSet)
    
    urlpatterns = [
        path('', include(router.urls)),
    
    ]
  • views.py

    from django.contrib.auth.models import User
    from rest_framework import viewsets
    from .serializers import UserSerializer, PostSerializer, CommentSerializer
    from blog.models import Post, Comment
    
    # ViewSets define the view behavior.
    class UserViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
    
    class PostViewSet(viewsets.ModelViewSet):
        queryset = Post.objects.all()
        serializer_class = PostSerializer    
    
    class CommentViewSet(viewsets.ModelViewSet):
        queryset = Comment.objects.all()
        serializer_class = CommentSerializer  
  • serializers.py

    from django.contrib.auth.models import User
    from rest_framework import serializers
    from blog.models import Post, Comment
    
    # Serializers define the API representation.
    class UserSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = User
            fields = ['url', 'username', 'email', 'is_staff']
    
    class PostSerializer(serializers.ModelSerializer):
        class Meta:
            model = Post
            # fields = '__all__'
            fields = ['id', 'title', 'image', 'like', 'category']
    
    class CommentSerializer(serializers.ModelSerializer):
        class Meta:
            model = Comment
            fields = '__all__'
            # fields = ['id', 'title', 'image', 'like', 'category']
  • viewsets를 사용하면 따로 CRUD를 구현할 필요 없이 한꺼번에 제공됨

  • 하지만 그 내부에서 커스터마이징하여 사용하기가 까다로움

  • 커스터마이징하여 사용하려면 Generic View를 사용하는 것이 유리!

Generic Views를 사용하여 user, post, comment 기능 구현

  • Generic Views 종류 : ListAPIView, CreateAPIView, RetieveAPIView, UpdateAPIView, DestroyAPIView

  • 구현하기 앞서 url과 그것에 매핑되는 view를 미리 정하는 것이 좋음

    • /api2/post/ (GET) ➡ ListAPIView
    • /api2/post/99/ (GET) ➡ RetrieveAPIView
    • /api2/comment/ (POST) ➡ CreateAPIView
  • urls.py

    from django.urls import path
    from . import views
    
    urlpatterns = [
      path('post/', views.PostListAPIView.as_view(), name='post-list'),
      path('post/<int:pk>/', views.PostRetrieveAPIView.as_view(), name='post-detail'),
      path('comment/', views.CommentCreateAPIView.as_view(), name='comment-create'),
    ]
  • views.py

    from rest_framework.generics import ListAPIView, RetrieveAPIView, CreateAPIView
    from blog.models import Post, Comment
    from .serializers import CommentSerializer, PostSerializer
    
    class PostListAPIView(ListAPIView):
      queryset = Post.objects.all()
      serializer_class = PostSerializer
    
    class PostRetrieveAPIView(RetrieveAPIView):
      queryset = Post.objects.all()
      serializer_class = PostSerializer
    
    class CommentCreateAPIView(CreateAPIView):
      queryset = Comment.objects.all()
      serializer_class = CommentSerializer
    • PostListAPIViewPostRetrieveAPIView는 로직이 다른데 queryset, serializer_class 코드는 동일함 ➡ 서로 다른 클래스(ListAPIView, RetrieveAPIView)를 상속받기 때문에 실제 동작도 다르게 동작함!

동작원리 자세히 살펴보기

  • 코드
    class PostListAPIView(ListAPIView):
        queryset = Post.objects.all()
        serializer_class = PostSerializer
    • queryset = Post.objects.all() : DB에서 데이터를 가져옴
    • serializer_class = PostSerializer : serialize 수행
  • Generic View의 로직
    • 1) DB에서 데이터를 가져옴
    • 2) 가져온 데이터를 serialize함
    • 3) client에게 response함
  • 이중 2번 로직(serialize)이 다름!
    • ListAPIView - PostSerializer(instance=, many=True)
    • RetrieveAPIView - PostSerializer(instance=, many=False)
      • DB에서 가져온 데이터를 PostSerializer의 instance 인자로 넣을 때, many=False를 인자로 주면 instance 하나만을 serialize 하라는 의미가 됨!

CDRF에서 확인

  • ListAPIView (get -> list)

    • list() 메서드 호출

    • DB로 부터 데이터를 가져옴(queryset)
    • 가져온 데이터(queryset)를 instance 인자에 넣고 many=True 옵션을 주고 있음
  • RetrieveAPIView (get -> retrieve)

    • retrieve() 메서드 호출

    • 테이블로부터 데이터를 가져옴
    • 가져온 데이터를 serializer 클래스에 instance 인자로 넣음
    • many인자는 따로 주지 않고 있음 -> default : many=False

Reference

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

profile
기록하는 습관

0개의 댓글