DRF mixins 상속을 통한 APIView

2022. 7. 12. 01:32강의 정리/Django REST Framework

반응형

출처 : https://www.inflearn.com/course/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%A5%EA%B3%A0-%EC%9B%B9%EC%84%9C%EB%B9%84%EC%8A%A4/dashboard

 

장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!

 

 


Mixin : 전통적인 다중 상속을 클래스의 부분 부분을 쪼개어 조립하는 것


DRF에서 지원하는 mixins

  • 파이썬에서는 mixin이라는 문법은 따로 없고, 상속 문법을 사용하여 구현된다.
  • 믹스인 클래스는 직접적으로 사용하는게 아니라 다른 클래스에 의해서 상속이 되어 사용된다.
  • 믹스인에는 create(), list() 등의 리소스를 생성하거나 가져오는 로직이 구현되어있다.
  • 로직만 구현되어 있을 뿐, http method와 연계하는 부분은 직접 연결해줘야 한다. 
    • CreateModelMixin : Create를 하는 일반적인 로직이 구현되어 있음.
    • ListModelMixin : 목록을 조회하는 로직
    • RetrieveModelMixin
    • UpdateModelMixin
    • DestroyModelMixin

 

CreateModelMixin

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)  
        
        # serializer 저장
        self.perform_create(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 {}
  • Http method에 따른 처리를 따로 구현 해주어야한다.

 


 

method별 로직 연결


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
	
    # Http method가 get일 때, self.list를 호출하겠다라고 매핑
    def get(self, request, *args, **kwargs):  
        return self.list(request, *args, **kwargs)  # mixins.ListModelMixin을 상속받아서 사용 가능
	
    # Http method가 post일 때 self.create를 호출하겠다라고 매핑
    def post(self, request, *args, **kwargs):  
        return self.create(request, *args, **kwargs) # mixins.CreateModelMixin을 상속받아서 사용 가능
  • ListModelMixin과 CreateModelMixin을 상속 받았기에 list와 create라는 멤버 변수가 생성된다.
  • get -> self.list, post -> self.create를 매번 같은 파라미터를 넘겨 연결하려니 번거롭다.

 

from rest_framework import generics
from rest_framework import mixins
class PostDetailAPIView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixi, 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)
  • 모든 Http method마다 직접 연결을 해야하니 번거롭다. 심지어 하나가 늘어남.

 

APIView의 일반적인 로직을 섞어서 재사용율을 높인게 mixins

mixins들보다 패턴화 한것이 Genenrics

 

Genenrics들을 더욱 정리한게 ViewSet이다.

 


 

여러 generic APIView (모두 GenericsAPIView 상속)


  • genenrics.APIView이름 : Http method -> 멤버 함수
  • generics.CreateAPIView : post → create
  • generics.ListAPIView : get → list
  • generics.RetrieveAPIView : get → retrieve
  • generics.DestroyAPIView : delete → destroy
  • generics.UpdateAPIView : put → update, patch → partial_update
  • generics.ListCreateAPIView : get → list, post → create
  • generics.RetrieveUpdateAPIView : get → retrieve, put → update, patch → partial_update
  • generics.RetrieveDestroyAPIView : get → retrieve, delete → destroy
  • generics.RetrieveUpdateDestroyAPIView : get → retrieve, put → update, patch → partial_update, delete → destroy

 

 


 

generic APIView  활용


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.ListCreateAPIView를 상속받아서 PostListAPIView를 구현한다.

 

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)
  • generics.RetrieveUpdateDestroyAPIVie를 상속받아서 PostDetailAPIView를 구현

 

 


 

적절한 generics APIView를 상속받기만 해도 원하는 기능을 구현할 수 있다.

 

직접 API View를 만들 수 있을 정도로 공부하기(내부를 이해하기 위해서)

 

ViewSet이 좋다고, ViewSet만 공부해서는 나중에 응용할 수 없다.

 

 

 

반응형

'강의 정리 > Django REST Framework' 카테고리의 다른 글

From과 Serializer 관점에서 DRF 비교  (0) 2022.07.13
DRF ViewSet과 Router  (0) 2022.07.13
DRF로 APIView, Json 응답뷰 만들기  (0) 2022.07.11
Django JSON 직렬화  (0) 2022.03.22
Django JSON 응답뷰  (0) 2022.03.12