요모조모 ʚɞ

[D.R.F] Generic CBV로 CRUD 구현하기 본문

개발/Django RESTful API

[D.R.F] Generic CBV로 CRUD 구현하기

Angela_OH 2021. 1. 20. 00:08

 

안녕하세요  ˘◡˘ 

오늘은 CRUD 구현하는 새로운 방법에 대해 소개하고자 합니다!

지난 시간까지는 APIView와 Mixins을 사용한 CRUD 구현하기에 대해 소개하였는데,

두 가지 방법 모두 코드의 불필요한 중복이 발생하였습니다.

이번 시간에는 Generic CBV (Class Based Views) 상속을 통해 코드의 중복을 좀 더 줄여보고자 합니다.

 

Generic CBV에 대한 기본적인 설명과 예제는 아래의 공식 문서를 참고하였습니다.

www.django-rest-framework.org/tutorial/3-class-based-views/#using-generic-class-based-views

 

3 - Class based views - Django REST framework

We can also write our API views using class-based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code DRY. We'll start by rewriting the root view as a cla

www.django-rest-framework.org

 

Generic CBV는 rest framework의 generics.py를 import 하여 사용하였습니다.

지난 시간에 다루었던 mixins의 경우에는 generics.py의 GenericAPIView를 상속받았습니다.

하지만 Generic CBV에서는 GenericAPIView가 아닌 다른 클래스를 상속받아 사용합니다!

이에 대한 자세한 소스 코드는 아래의 github에서 확인해볼 수 있습니다.

github.com/encode/django-rest-framework/blob/master/rest_framework/generics.py

 

encode/django-rest-framework

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

github.com

 

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

Generic CBV를 활용하여 views.py를 작성하였습니다.

APIView와 mixins을 사용했을 때보다 코드가 훨씬 더 간결해진 것을 확인할 수 있습니다.

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

# Blog의 목록을 보여주는 역할
class BlogList(generics.ListCreateAPIView):
    queryset = Blog.objects.all()
    serializer_class = BlogSerializer

# Blog의 detail을 보여주는 역할
class BlogDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Blog.objects.all()
    serializer_class = BlogSerializer

 

generics.py의 일부

 

Generic CBV에서 상속받은 generics.py 코드를 확인해보면 (위의 github 링크 참고)

각각의 HTTP method 기능을 하는 클래스가 구현되어 있음을 알 수 있습니다.

예를 들어 CreateAPIView는 새로운 객체를 생성하는 POST의 기능을,

ListAPIView는 객체의 전체 목록을 보여주는 GET의 기능을 수행합니다.

이에 대한 내용은 함수의 이름으로도 유추해볼 수 있고, 공식 자료를 참고하여 확인할 수 있습니다!

이 외에도 여러 기능을 가지고 있는 ListCreateAPIView, RetrieveUpdateAPIView 등 용도에 맞는 다양한 클래스가 존재하기 때문에,

우리는 원하는 기능의 클래스를 상속하여 사용할 수 있습니다.

 

해당 예제의 경우에는 Blog 객체의 전체 목록 보기 + 새로운 객체 등록을 위해 ListCreateAPIView 클래스와

Blog detail 보기 + 객체 수정 + 객체 삭제를 위해 RetrieveUpdateDestroyAPIView 클래스를 상속하였습니다.

 

추가로 generics.py에서 사용한 클래스(ex. ListAPIView)에서는 GenericAPIView를 다시 상속받고 있기 때문에

Generic CBV에서도 querysetserializer_class를 별도로 지정해주었습니다.

 

urls.py

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

urls.py도 이전과 동일하게 작성하였습니다.

아래의 코드는 project app 폴더 내부에 urls.py라는 파일을 별도로 생성한 후 작성하였습니다.

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

urlpatterns =[
    path('blog/', views.BlogList.as_view()),
    path('blog/<int:pk>/', views.BlogDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

 

이후 프로젝트 폴더 내부의 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')),
]

 

위와 같이 코드를 작성하게 되면 CRUD의 기능을 구현할 수 있습니다.

아래의 사진은 웹 서버를 실행시켰을 때의 Create 기능을 수행하는 페이지의 일부입니다!

(이 외의 사진은 지난 시간의 mixins 결과 화면과 동일합니다.)

127.0.0.1:8000/blog의 POST

 

이번 시간에는 CBV의 상속 개념을 더욱 활용하여 불필요한 코드를 줄여보았습니다!

확실히 APIView와 mixins을 활용했을 때보다 코드가 (많이) 간결해진 것을 알 수 있습니다.ㅎㅎ

하지만 APIView의 경우에는 커스터마이징에 용이하기 때문에 필요에 따라 APIView 등을 상속받아 사용할 수 있습니다.

다음 게시글에서는 CRUD의 (드디어) 마지막 단계인 ViewSet에 대해 알아보도록 하겠습니다!

 

Comments