앞선 포스트에서 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 |