[DRF] 공식 문서 - views의 정리 4 - CBV(Mixins)
1. Mixins
- mixin class들은 기본적인 view 동작을 제공하기 위해 사용되는 action들을 제공한다.
- 주의해야 할 점은 mixin class들은 .get() 이나 .post()와 같은 handler method를 직접 정의하는 것이 아닌 action method를 제공하는 것이다.
- 행위들의 좀 더 유연한 구성을 만들 수 있도록 한다.
- rest_framework.mixins로부터 import해 사용할 수 있다.
- APIview를 사속하는 경우와 GenericAPIview를 상속하는 경우의 차이
from rest_framework.mixins import RetrieveModelMixin
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelRetrieveAPIView(RetrieveModelMixin, APIView):
"""
A view for retrieving a single instance of YourModel using RetrieveModelMixin and APIView.
"""
model = YourModel
serializer_class = YourModelSerializer
1) ListModelMixin
- queryset을 나열할 수 있는 .list(request, *args, **kwargs) 메서드를 제공한다.
- 만약 queryset의 내용이 존재한다면 200 OK response를 반환한다.
- serialized된 queryset가 response의 body가 된다.
- response data는 선택적으로 페이징될 수 있다.
- APIview 사용시
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
class YourAPIView(APIView):
pagination_class = YourModelPagination
def get(self, request, *args, **kwargs):
# Step 1: Get the base queryset
queryset = YourModel.objects.all()
# Step 2: Apply any necessary filtering to the queryset
queryset = self.filter_queryset(queryset) # Using filter_queryset here
# Step 3: Check if pagination is requested
page = self.paginate_queryset(queryset)
if page is not None:
# Step 4a: If paginated, serialize the paginated data
serializer = YourModelSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
else:
# Step 4b: If not paginated, serialize the entire queryset
serializer = YourModelSerializer(queryset, many=True)
return Response(serializer.data)
- GenericAPIView 사용시
from rest_framework.mixins import ListModelMixin
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
class YourModelListView(ListModelMixin, GenericAPIView):
queryset = YourModel.objects.all()
serializer_class = YourModelSerializer
pagination_class = YourModelPagination # Use your custom pagination class
def get(self, request, *args, **kwargs):
# Step 1: Get the base queryset
queryset = self.get_queryset()
# Step 2: Apply any necessary filtering to the queryset
queryset = self.filter_queryset(queryset)
# Step 3: Check if pagination is requested
page = self.paginate_queryset(queryset)
if page is not None:
# Step 4a: If paginated, serialize the paginated data
serializer = YourModelSerializer(page, many=True)
return self.get_paginated_response(serializer.data)
else:
# Step 4b: If not paginated, serialize the entire queryset
serializer = YourModelSerializer(queryset, many=True)
return Response(serializer.data)
2) CreateModelMixin
- 새로운 model instance를 생성하고 저장할 수 있는 .create(request, *args, **kwargs) 메서드를 제공한다.
- 만약 object가 생성된다면 201 Created response를 반환한다.
- serialized된 object가 response의 body가 된다.
- 만약 표현에 url이 key name으로 포함되어 있다면, response의 Location header가 value 값과 같이 채워진다.
- 만약 제공된 request data로 object 생성이 불가능하다면 400 Bad Request response가 error detail을 body로 가지고 반환된다.
from rest_framework.mixins import CreateModelMixin
from rest_framework.response import Response
from rest_framework.status import HTTP_201_CREATED, HTTP_400_BAD_REQUEST
from rest_framework.views import APIView
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelCreateView(CreateModelMixin, APIView):
def post(self, request, *args, **kwargs):
# Step 1: Deserialize the request data using the serializer
serializer = YourModelSerializer(data=request.data)
# Step 2: Validate the serializer data
if serializer.is_valid():
# Step 3: Save the validated data to create a new instance
self.perform_create(serializer)
# Step 4: Return a 201 Created response with the serialized representation
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=HTTP_201_CREATED, headers=headers)
else:
# Step 5: Return a 400 Bad Request response with the error details
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
def perform_create(self, serializer):
# Custom method to save the instance to the database
serializer.save()
- mixin이 status와 header 코드를 적절하게 정의를 해준다 때문에 생략할 수 있다.
from rest_framework.mixins import CreateModelMixin
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelCreateView(CreateModelMixin, APIView):
def post(self, request, *args, **kwargs):
# Step 1: Deserialize the request data using the serializer
serializer = YourModelSerializer(data=request.data)
# Step 2: Validate the serializer data
if serializer.is_valid():
# Step 3: Save the validated data to create a new instance
self.perform_create(serializer)
# Step 4: Return a response with the serialized representation
return Response(serializer.data)
else:
# Step 5: Return a response with the error details
return Response(serializer.errors)
def perform_create(self, serializer):
# Custom method to save the instance to the database
serializer.save()
3) RetrieveModelMixin
- 현재 존재하고 있는 model instacne를 검색해 response로 반환하는 .retrieve(request, *args, **kwargs) 메서드를 제공한다.
- 만약 object가 검색된다면 200 OK response가 반환된다.
- serialized된 object가 response의 body가 된다.
- 검색되지 않는다면 404 Not Found를 반환한다.
from rest_framework.mixins import RetrieveModelMixin
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelRetrieveAPIView(RetrieveModelMixin, APIView):
"""
A view for retrieving a single instance of YourModel using RetrieveModelMixin and APIView.
"""
model = YourModel
serializer_class = YourModelSerializer
4) UpdateModelMixin
- 현재 존재하고 있는 model instance를 업데이트하고 저장할 수 있는 .update(request, *args, **kwargs) 메서드를 제공한다. -> PUT
- 또한 update 메서드와 비슷하지만 모든 필드를 선택적으로 업데이트할 수 있는 .partial_update(request, *args, **kwargs) 메서드를 제공한다. -> PATCH
- 만약 object의 업데이트에 성공한다면 200 OK를 반환한다.
- serialized된 object가 response의 body가 된다.
- 만약 object의 업데이트에 실패하게 되면 400 Bad Request response가 error detail을 body로 가지고 반환된다.
from rest_framework.mixins import UpdateModelMixin
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelUpdateAPIView(UpdateModelMixin, GenericAPIView):
"""
A view for updating a single instance of YourModel using UpdateModelMixin and GenericAPIView.
"""
queryset = YourModel.objects.all()
serializer_class = YourModelSerializer
def put(self, request, *args, **kwargs):
"""
Handle PUT requests to update a single instance of YourModel.
"""
return self.update(request, *args, **kwargs)
def perform_update(self, serializer):
"""
Override this method to add custom logic when updating the model instance.
This method is specific to UpdateModelMixin and may be used for any additional customization.
By default, it saves the serializer.
"""
# Example: Add custom logic before saving the instance
serializer.save()
5) DestroyModelMixin
- 현재 존재하고 있는 model instance를 삭제하는 .destroy(request, *args, **kwargs) 메서드를 제공한다.
- 만약 object가 성공적으로 삭제되면 204 No Content response를 반환한다.
- 삭제에 실패한다면 404 Not Found를 반환한다.
from rest_framework.mixins import DestroyModelMixin
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import YourModel
from .serializers import YourModelSerializer
class YourModelDestroyAPIView(DestroyModelMixin, GenericAPIView):
"""
A view for destroying a single instance of YourModel using DestroyModelMixin and GenericAPIView.
"""
queryset = YourModel.objects.all()
serializer_class = YourModelSerializer
def delete(self, request, *args, **kwargs):
"""
Handle DELETE requests to destroy a single instance of YourModel.
"""
return self.destroy(request, *args, **kwargs)
def perform_destroy(self, instance):
"""
Override this method to add custom logic when destroying the model instance.
This method is specific to DestroyModelMixin and may be used for any additional customization.
By default, it deletes the instance.
"""
# Example: Add custom logic before deleting the instance
instance.delete()
- 공식 사이트 문서 : https://www.django-rest-framework.org/api-guide/generic-views/#mixins
- reference :
'Django REST Framework > DRF 일반' 카테고리의 다른 글
[DRF] 공식 문서 - views의 정리 6 - CBV(Viewsets) (1) | 2024.01.11 |
---|---|
[DRF] 공식 문서 - views의 정리 5 - CBV(Concrete View Classes) (1) | 2024.01.11 |
[DRF] 공식 문서 - views의 정리 3 - CBV(Generic views) (0) | 2024.01.10 |
[DRF] 공식 문서 - views의 정리 2 - CBV(APIView) (0) | 2024.01.08 |
[DRF] 공식 문서 - views의 정리 1 - FBV(api_view) (0) | 2024.01.08 |
댓글