파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.
필요에 의해 다양한 믹스인을 만드실 수 있어요.
https://github.com/encode/django-rest-framework/blob/3.11.0/rest_framework/mixins.py
파이썬 클래스의 상속문법이 이용되어 구현된다.
믹스인 클래스는 직접적으로 사용되는게 아니라 다른 클래스에 의해서 상속이 이루어 지며 사용된다.
로직만 구현되어 있을 뿐, 실제 http method와 연계하는 부분은 우리가 따로 연결해줘야 한다.
# https://github.com/encode/django-rest-framework/blob/3.11.0/rest_framework/mixins.py#L12
class CreateModelMixin:
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True) # 유효성 검사 통과를 못하면 예외발생
self.perform_create(serializer) # serializer 저장
headers = self.get_success_headers(serializer.data) # 성공했을 때 응답 해줄 헤더 목록을 헤더에 넣는다.
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) # 응답
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
from rest_framework import generics
from rest_framework import mixins
class PostListAPIView(**mixins.ListModelMixin**, **mixins.CreateModelMixin**, generics.GenericAPIView): # generics.GenericAPIView가 가장 마지막에 상속받아야 한다.
queryset = Post.objects.all()
serializer_class = PostSerializer
def get(self, request, *args, **kwargs): # get일 때, self.list를 호출하겠다라고 매핑
return **self.list**(request, *args, **kwargs) # mixins.ListModelMixin을 상속받아서 사용 가능
def post(self, request, *args, **kwargs): # post일 때 self.create를 호출하겠다라고 매핑
return **self.create**(request, *args, **kwargs) # mixins.CreateModelMixin을 상속받아서 사용 가능
"""get -> self.list, post -> self.create를 매번 같은 파라미터를 넘겨 연결하려니 번거롭다."""
from rest_framework import generics
from rest_framework import mixins
class PostDetailAPIView(**mixins.RetrieveModelMixin**, **mixins.UpdateModelMixin**, **mixins.DestroyModelMixin**, generics.GenericAPIView): # generics.GenericAPIView가 가장 마지막에 상속받아야 한다.
queryset = Post.objects.all()
serializer_class = PostSerializer
def get(self, request, *args, **kwargs):
return **self.retrieve**(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return **self.update**(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return **self.destroy**(request, *args, **kwargs)
"""마찬가지로 매번 연결하려니 번거롭다. 심지어 하나가 늘어남.."""
⇒매번 연결하는 부분을 패턴화 해서 정리한 것이 Generics이다.
View 구현 시 상속받는 클래스의 추상화 정도: APIView < mixins < Generics < ViewSet
- mixins : APIView에서 일반적인 로직들을 섞어서 재사용성을 높인 것
- Generics : mixins 사용을 패턴화해서 정리함
- ViewSet : Generics를 한번 더 합쳐서 정리
https://github.com/encode/django-rest-framework/blob/3.11.0/rest_framework/generics.py
직접 http메소드와 로직을 연결하지 않고, 이미 연결되어있는 클래스를 상속받아 사용한다.
"""generics.ListCreateAPIView를 상속받아서 post list view를 구현"""
from rest_framework import generics
class PostListAPIView(generics.ListCreateAPIView): # 아래 ListCreateAPIView를 상속
queryset = Post.objects.all()
serializer_class = PostSerializer
# rest_framework/generics.py
class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView):
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
"""generics.RetrieveUpdateDestroyAPIVie를 상속받아서 post detail view를 구현"""
from rest_framework import generics
class PostDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
# rest_framework/generics.py
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, GenericAPIView):
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)