요모조모 ʚɞ

[D.R.F] ViewSets으로 CRUD 구현하기 본문

개발/Django RESTful API

[D.R.F] ViewSets으로 CRUD 구현하기

Angela_OH 2021. 1. 21. 01:02

 

안녕하세요  ๑(•‿•)๑ 

오늘은 CRUD 구현의 마지막 방식인 ViewSet을 사용해보도록 하겠습니다.

APIView에서부터 Mixins, 그리고 Generic CBV를 거쳐 ViewSet까지 왔네요 ㅎㅎ

ViewSet은 상속을 여러 번 거친 만큼 코드가 매우 간결해졌답니다.

Viewset에 대한 내용과 예제 코드는 아래의 공식 문서를 참고하였습니다.

www.django-rest-framework.org/tutorial/6-viewsets-and-routers/

 

6 - Viewsets and routers - Django REST framework

REST framework includes an abstraction for dealing with ViewSets, that allows the developer to concentrate on modeling the state and interactions of the API, and leave the URL construction to be handled automatically, based on common conventions. ViewSet c

www.django-rest-framework.org

 

models.py

모델은 기존과 동일한 Blog 모델을 사용하도록 하겠습니다.

from django.db import models
from django.conf import settings

class Blog(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()

 

serializers.py

serailizer 역시 이전과 동일한 BlogSerializer를 사용하였습니다.

from .models import Blog
from rest_framework import serializers

class BlogSerializer(serializers.ModelSerializer):
    class Meta:
        model = Blog
        fields = '__all__'

 

views.py

ViewSet을 활용하여 view를 작성하였습니다.

코드가 APIView에 비하면 매!!우 간결해진 것을 알 수 있습니다.

CRUD 기능이 클래스 3줄로,, 끝나버린 것이죠

from .models import Blog
from .serializers import BlogSerializer
from rest_framework import viewsets

# Blog의 목록, detail 보여주기, 수정하기, 삭제하기 모두 가능
class BlogViewSet(viewsets.ModelViewSet):
    queryset = Blog.objects.all()
    serializer_class = BlogSerializer

 

코드가 이렇게 간결할 수 있었던 것은 클래스의 상속 개념을 활용하였기 때문입니다.

우리는 APIView와 Mixins, Generic CBV, ViewSet를 거치면서 상속을 통해 불필요한 코드를 점점 줄여나갔습니다.

실제로 ViewSet의 코드 내부를 살펴보시면 기존에 보았던 익숙한 클래스들을 확인할 수 있습니다.

viewsets.py의 ModelViewSet

우리가 views.py에서 상속받아 사용했던 ModelViewSet 클래스를 살펴보면, Mixins 클래스를 상속받고 있음을 확인할 수 있습니다.

CreateModelMixin, RetrieveModelMixin 등 CRUD의 기능을 하는 다양한 클래스를 상속받은 것을 확인할 수 있죠.

이 외에도 상속 받아 사용한 GenericViewSet의 내부를 살펴보면 아래와 같이 generics의 GenericAPIView를 상속 받고 있습니다. 

(Mixins으로 CRUD를 구현할 때 상속받아와서 사용했던 클래스죠!)

viewsets.py의 GenericViewSet

이처럼 복잡한 CRUD를 rest framework에서 미리 정의한 클래스를 상속받아 아주 간결하게 구현할 수 있었습니다.

이와 관련된 공식 viewsets.py 코드는 아래의 github을 참고해주세요.

github.com/encode/django-rest-framework/blob/19655edbf782aa1fbdd7f8cd56ff9e0b7786ad3c/rest_framework/viewsets.py

 

encode/django-rest-framework

Web APIs for Django. 🎸. Contribute to encode/django-rest-framework development by creating an account on GitHub.

github.com

 

urls.py

마지막으로 urls.py 입니다.

ViewSet의 경우에는 하나의 class에 Blog 목록과 detail을 보여주는 기능이 모두 존재합니다.

하지만 이를 하나의 path 함수로는 표현할 수 없습니다.

왜냐하면 Blog 목록을 보여주는 url의 경우에는 pk 값이 필요가 없지만,

detail을 보여주기 위해서는 pk 값이 반드시 필요하기 때문입니다.

따라서 ViewSet을 사용하기 위해서는 서로 다른 path 함수를 하나로 묶어주는 과정이 필요합니다.

path 함수를 묶어주기 위한 방법으로는 두 가지가 존재합니다.

1. as_view() 함수 활용하기

as_view() 함수를 사용하여 mapping 관계를 처리해주었습니다.

함수의 인자로는 http method와 처리할 함수의 이름을 작성해주었습니다.

처리할 함수의 이름은 list, create, retrieve, update, destory 등이 있으며 이것은 viewsets.py에서 확인할 수 있습니다.

from django.urls import path
from .views import BlogViewSet

# Blog 목록 보여주기
blog_list = BlogViewSet.as_view({
    'get': 'list',
    'post': 'create'
})

# Blog detail 보여주기 + 수정 + 삭제
blog_detail = BlogViewSet.as_view({
    'get': 'retrieve',
    'put': 'update',
    'delete': 'destroy'
})

urlpatterns =[
    path('blog/', blog_list),
    path('blog/<int:pk>/', blog_detail),
]

2. router 활용하기

다음으로는 rest framework의 DefaultRouter라는 객체를 생성하여,

mapping 하고자 하는 view를 등록해주었습니다.

from django.urls import path, include
from .views import BlogViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
# 첫 번째 인자는 url의 prefix
# 두 번째 인자는 ViewSet
router.register('blog', BlogViewSet)

urlpatterns =[
    path('', include(router.urls))
]

 

이후 프로젝트 폴더 내부의 urls.py에 아래의 내용을 작성해주었습니다.

from django.contrib import admin
from django.urls import path, include
from project import urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('project.urls')),
]

 

마지막으로 웹 서버를 실행하게 되면 아래와 같이 Blog 목록을 보여주고 객체를 등록할 수 있는 화면과,

 

127.0.0.1:8000/blog/

 

Blog detail을 보고 삭제, 수정을 가능하게 하는 페이지가 구현되었음을 확인할 수 있습니다.

 

127.0.0.1:8000/blog/<int:pk>

 

지금까지 다양한 방식을 활용하여 Django REST Framework에서의 CRUD를 구현해보았습니다.

FBV(Function Based View)로 CRUD를 구현하면 굉장히 많은 views.py 파일이 필요했었는데,

CBV로 구현하니 상속의 특징을 활용하여 매우 간결하게 구현할 수 있었습니다.

 

다음 게시글에서는 Blog 객체에 커스텀 사용자 정보를 등록해보도록 하겠습니다.!

To be continued  ...

Comments