Published 2023. 4. 23. 21:56

앞선 포스트에서 api view들을 다시 압축한 modelviewset 이 있음을 미리 밝혔는데, 오늘은 이 modelviewset에 대해서 자세히 해보는 시간을 가지고 싶다.

https://scarlet0star.tistory.com/49

 

django : generic view

django에서 가장 편한 기능을 꼽으라고 한다면 그 중 하나는 나는 generic views 라고 말하고 싶다. generic views는 웹개발시 사용되는 반복되는 패턴을 쉽게 처리할 수 있도록 미리 클래스를 만들어둔거

scarlet0star.tistory.com

https://scarlet0star.tistory.com/58

 

DRF : Serializer

우리는 Representational State Transfer (REST)의 개념을 이해하면서, RESTful한 웹 어플리케이션을 만들기 위하여 서버와 클라이언트를 분리해야 함을 깨달았다. 서버와 클라이언트는 Application Programming Inte

scarlet0star.tistory.com

 

위 포스트에서 언급했듯이 ModelViewSet은 RESTful한 APIView들로 구성된 뷰 세트다. 기본 구성부터가 RESTful하게 구성되어있는 지라 이를 이용하면 매우 편리하고 간단하게 기존에 생성한 모델을 기반으로 API를 생성할 수 있다. 상속을 받는 만큼 오버라이딩을 통해서 커스터마이징이 역시 가능하다.

 

from rest_framework import viewsets

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

기본적인 구성은 다음과 같이 쓸 수 있다. 이것만으로도 전체 과정은 거의 끝. views.py에서는 준비 끝이다. 위 구성을 가볍게 살펴보면 rest_framewor에서 viewsets을 임포트하여 modelviewset을 상속받았다. 이후 ListView에 전달할 queryset을 지정하고, 사용할 시리얼라이저를 지정해준다. 끝. 정말 말도 안되게 짧은 코드로 API가 완성되었다.

 

이제 이 view를 사용할 수 있도록 urls.py를 설정하도록 하자.

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

router = DefaultRouter()
router.register(r'my-model', views.MyModelViewSet)

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

modelviewset을 이용하기 위해서는 DRF Router를 사용해야한다. DRF Router는 Viewset에 존재하는 각각의 request에 대해서 자동으로 엔드포인트를 지정하고 메서드에 따른 구분처리를 해주는 함수이다. 위의 코드는 아래와 같은 엔드포인트들을 자동으로 생성해준다.

  • GET api/my-model/: 목록 조회 (list)
  • POST api/my-model/: 새로운 항목 생성 (create)
  • GET api/my-model/{id}/: 특정 항목 조회 (retrieve)
  • PUT api/my-model/{id}/: 특정 항목 수정 (update)
  • PATCH api/my-model/{id}/: 특정 항목의 일부 수정 (partial update)
  • DELETE api/my-model/{id}/: 특정 항목 삭제 (destroy)

 

from rest_framework import routers
from myapp.views import UserViewSet, ProfileViewSet

router = routers.DefaultRouter()
router.register(r'user', UserViewSet)
router.register(r'profile', ProfileViewSet)

복수의 ViewSet을 등록하는 것도 가능하다. 이제는 Model - Serializer - view - urls conf 모두 완료했다.

 

만약 별도의 로직이 추가적으로 필요하여 viewset에 커스터마이징이 필요하다면 세가지 방법이 있다.

  • 믹스인(Mixin) 클래스를 사용하기:
    • 믹스인 클래스를 생성하고 이를 상속받아서 이용하는 방법이다. 개인적으로 너무나 큰 방법이라 생각해서 미리 생성된 믹스인 클래스들을 이용하는 것 말고는 사소하게 이용하기 힘들어 보인다. 사소한 로직 변경이 아닌 클래스 설계 차원에서 변경이 필요하다면 사용하기 좋은 방법이라고 생각한다
class MyModelViewSetMixin:
    def list(self, request, *args, **kwargs):
        # 전 처리 로직
        response = super().list(request, *args, **kwargs)
        # 후 처리 로직
        return response

class MyModelViewSet(MyModelViewSetMixin, viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

 

  • DRF에서 제공하는 perform_* 메서드를 오버라이딩하기:
    • DRF의 ModelViewSet 클래스는 perform_create, perform_update, perform_destroy와 같은 메서드를 제공하는데, 이 메서드들은 각각 create, update, destroy 동작에 대한 실제 데이터베이스 작업을 수행한다. 이 메서드들을 오버라이딩하여 전후 처리 로직을 추가할 수 있다. 사소한 변경이라면 이 경우가 적절하다고 생각한다.
class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

    def perform_create(self, serializer):
        # 전 처리 로직
        instance = super().perform_create(serializer)
        # 후 처리 로직
        return instance

 

  • 시그널 사용하기:
    • 객체가 저장되거나 삭제될 때 자동으로 관련 작업이 수행되도록 하려면 post_save 또는 post_delete 시그널을 사용할 수 있다. 시그널 핸들러의 경우 디버깅이 어렵다는 단점이 있다는데, 그럼에도 시그널을 통해 느슨한 구현을 할 수 있으니 적절히 사용할 수 있다면 사용해도 괜찮다고 생각한다.

https://scarlet0star.tistory.com/46

 

django : Signal

시그널이란 것을 접하게 된 것은 참 우연찮은 기회인데, 구글 소셜 로그인을 사용하려고 시도했을 당시에 소셜 계정이 생성되는 것은 확인했으나 관련된 모델 인스턴스가 생성되지 않아 어떻게

scarlet0star.tistory.com

 

 

'Python > Django' 카테고리의 다른 글

테스트 기반 개발과 테스트  (0) 2023.05.01
DRF serializer 추가) nested field, method field  (0) 2023.04.24
DRF : Serializer  (0) 2023.04.23
django : generic view  (0) 2023.04.17
django : Signal  (0) 2023.04.17
복사했습니다!