DRF ModelViewset 사용법
Posted on 2021-08-30 by GKSRUDTN99
Django Rest Framework
DRF
ModelViewSet
ModelViewSet을 왜 사용하는가?
DjangoFilterBackend
, SearchFilter
, OrderingFilter
를 이용해 필터, 검색, 정렬이 쉽게 가능하다.
CRUD를 한번에 구현할 수 있다.
사용방법
1. django_filter
를 pip로 설치하고, INSTALLED_APPS
에 django_filters
를 추가한다.
2. 필요한 모듈들을 임포트한다.
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework import viewsets
3. ModelViewSet
을 확장하는 새로운 클래스를 정의한다.
class ReviewViewSet(viewsets.ModelViewSet):
queryset = Review.objects.all()
serializer_class = ReviewSerializer
permission_classes = [permissions.AllowAny, ]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
filterset_fields = ["user"]
ordering_fields = ["upload_at"]
search_fields = ["title"]
4. urls.py
에 url을 등록한다.
from django.urls import include
router = DefaultRouter()
로router
를 선언한다.router.register('', ReviewViewSet)
라우터를 등록한다.path('', include(router.urls)
를urlpatterns
에 추가한다.
from django.urls import path, include
from .views import PostReviewView, ReviewListView, ReviewViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('', ReviewViewSet)
urlpatterns = [
path('post/', PostReviewView.as_view(), name='post_review'),
path('list/', ReviewListView.as_view(), name='review_list'),
path('', include(router.urls)),
]
ModelViewSet의 추가적인 Custom 방법
ModelViewSet은 list
, create
, retrieve
, update
, partial_update
, destroy
의 6가지 action들을 가지고 있다.
예를 들어, 새로운 객체를 만들 때, user 필드를 로그인 된 유저로 자동으로 채우고 싶다면, 다음과 같이 custom할 수 있다.
class ReviewViewSet(viewsets.ModelViewSet):
(... 생략 ...)
def create(self, request):
serializer = self.get_serializer(data=request.data)
stylist = Stylist.objects.get(pk=request.data['stylist'])
if serializer.is_valid() and stylist.user != self.request.user:
serializer.save(user=self.request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
list
필드를 override할 때, DjangoFilterBackend로 필터링을 하고 싶다면, self.filter_queryset(queryset)
을 사용한다.
class MessageViewSet(viewsets.ModelViewSet):
(... 생략 ...)
def list(self, request, *args, **kwargs):
messages = Message.objects.all().order_by('-created_at')
messages = self.filter_queryset(messages)
page = self.paginate_queryset(messages)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(page, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
action decorator를 통해 위의 6가지 기능 외 추가적인 기능도 구현이 가능하다.
from rest_framework.decorators import action
...
@action(detail=True, methods=['GET'], name='Bookmark')
def bookmark(self, request, pk=None):
if self.request.user.is_authenticated:
stylist = Stylist.objects.get(pk=pk)
if self.request.user.bookmarks.filter(pk=pk).count() == 1:
self.request.user.bookmarks.remove(pk)
stylist.like_count -= 1
else:
self.request.user.bookmarks.add(pk)
stylist.like_count += 1
self.request.user.save()
stylist.save()
return Response("OK", status=status.HTTP_200_OK)
return Response("Not Authenticated", status=status.HTTP_401_UNAUTHORIZED)
기타
실습 환경
Django==3.2.4
django-cors-headers==3.7.0
djangorestframework==3.11.1
django-filter==2.4.0
Djagno와 DRF의 버전 문제로, TemplateNotExist문제나 ImportError가 발생하기도 한다.
DRF Viewset Reference
https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset