DRF API View

김동완·2022년 7월 23일
0

DRF For Biginners

목록 보기
4/8
post-thumbnail
post-custom-banner

List/Create API View

  • APIView를 상속받아 간단히, 게시글을 작성하고 조회할 수 있다.

Model

class Todo(TrackingModel) :
    
    title = models.CharField(max_length=255)
    desc = models.TextField()
    is_complete = models.BooleanField(default=False)
    owner = models.ForeignKey(to=User,on_delete=models.CASCADE)
    
    def __str__(self) :
        return self.title
  • is_complete는 Todo를 만들 때 기본적으로 False로 설정해, Todo를 생성 시 기본적으로 끝나지 않은 상태로 등록한다.
  • Todo의 주인은 Todo를 생성한 User를 참조해서 등록한다.

Serializer

class TodoSerializer(ModelSerializer) :
    
    class Meta:
        model=Todo
        
        fields = ('title','desc','is_complete',)
  • is_complete 는 default 값이 있기 때문에, title과 desc를 입력받게 하고, 직렬화 필드를 거치면, 해당 3가지 필드를 serializer에 담아서 응답을 보낸다.

Create

class CreateTodoAPIView(CreateAPIView) :
    
    serializer_class =TodoSerializer
    permission_classes=(IsAuthenticated,)
    
    def perform_create(self, serializer):
        return serializer.save(owner=self.request.user)
  • CreateAPIView는 mixins.CreateModelMixin과 GenericAPIView를 상속받는다.
# CreateAPIView
class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView):
    """
    Concrete view for creating a model instance.
    """
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
    
#mixins.CreateModelMixin
class CreateModelMixin:
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        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 {}
  • 데이터가 POST 요청으로 들어오면, serializer 필드에 요청된 데이터를 넣고, 모델에 새로운 Instance를 추가한다.
  • post 요청을 받으면, 넘어온 데이터로 create를 진행한다.
  • create는 CreateModelMixin class에서 상속받는데, serializer_classs에서 선언한 직렬화기로, 직렬화를 진행한다.
  • 유효성 검사를 끝내면 perform_create 함수에 직렬화가 끝낸 정보를 넣어주는데, 이를 custom 하여, 요청한 user를 owner로 선언해준다.

List

class TodoListAPIView(ListAPIView) :
    
    serializer_class = TodoSerializer
    permission_classes=(IsAuthenticated,)
    
    
    queryset=Todo.objects.all()
    
    
    def get_queryset(self):
        return Todo.objects.filter(owner=self.request.user)
  • List API View는 get 요청에 대해 queryset 형태로 데이터를 리턴하는 클래스이다.

  • 해당 클래스에는 필수적으로 queryset을 정의해야 하며, 이를 정의하면 다른 override 없이 queryset을 리턴한다.

    •   class TodoListAPIView(ListAPIView) :
         
            serializer_class = TodoSerializer
            queryset=Todo.objects.all()
  • 하지만 queryset에 대해서 custom하여 request에 담긴 data를 가지고 오고 싶은 경우 get_queryset 함수를 재정의 하여 해결할 수 있다.

    •   class TodoListAPIView(ListAPIView) :
            
            serializer_class = TodoSerializer
            def get_queryset(self):
                return Todo.objects.filter(owner=self.request.user)
  • 해당 TodoListAPIView의 경우 get_queryset을 재정의 했기 때문에, queryset을 요청하지 않아도 되며, queryset 요청에 대해 요청한 유저가 작성한 유저인 경우에만 불러온다.

  • 일반적으로 queryset을 사용하여 보다 깔끔히 표시하지만, request에서 data를 가져와야 할 경우에는 필수적으로 get_queryset을 사용해야한다.

Stackoverflow 참고 글

https://stackoverflow.com/questions/19707237/use-get-queryset-method-or-set-queryset-variable

  • queryset서버를 시작할 때 쿼리 세트가 한 번만 생성되며, 반면 get_queryset에 모든 요청에 대해 메서드가 호출된다.

    • 유용한 또 다른 예 get_queryset는 콜러블을 기반으로 필터링하려는 경우입니다. 예를 들어 오늘의 투표를 반환합니다.

      class IndexView(generic.ListView):
          def get_queryset(self):
              """Returns Polls that were created today"""
              return Poll.active.filter(pub_date=date.today())

      queryset를 설정하여 동일한 작업을 시도 하면 뷰가 로드될 때 querysetdate.today()가 한 번만 호출되고 잠시 후 뷰가 잘못된 결과를 표시합니다.

      class IndexView(generic.ListView):
          # don't do this!
          queryset = Poll.active.filter(pub_date=date.today())

ListCreateAPIView

  • List와 Create 기능을 한 번에 이용할 수 있는 API View이다.
class TodosAPIView(ListCreateAPIView) :
    serializer_class =TodoSerializer
    permission_classes=(IsAuthenticated,)
    def perform_create(self, serializer):
        return serializer.save(owner=self.request.user)
    # queryset=Todo.objects.all()
    def get_queryset(self):
        return Todo.objects.filter(owner=self.request.user)

RetrieveUpdateDestroyAPIView

  • get,put,delete,patch를 이용할 수 있다.
  • lookup_field를 이용해 객체를 찾을 변수를 설정하고 url에서 요청받아, detail을 조회할 수 있다.
class TodoDetailAPIView(RetrieveUpdateDestroyAPIView) :
    serializer_class =TodoSerializer
    permission_classes=(IsAuthenticated,)
    
    lookup_field="id"
    
    def get_queryset(self):
        return Todo.objects.filter(owner=self.request.user)

RetrieveUpdateDestroyAPIView

class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):
    """
    Concrete view for retrieving, updating or deleting a model instance.
    """
    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)
profile
내가 공부한 내용들이 누군가에게 도움이 될지 몰라서 쓰는 벨로그
post-custom-banner

0개의 댓글