Server/django

[Django] View of DRF ( Django Rest Framework )

또잉코딩 2020. 5. 4. 13:46

 

 

CBV

 

3 - Class based views - Django REST framework

We can also write our API views using class-based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code DRY. We'll start by rewriting the root view as a cla

www.django-rest-framework.org

class <클래스이름>(APIView):

    def <내가 필요로 하는 HTTP Method>:

        그 HTTP Method로 어떻게 처리할지는 직접 정의하기

 

views.py

from .models import Post
from .serializer import PostSerializer
from rest_framework import viewsets

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter

# django rest framework -> router -> url

router = DefaultRouter()
router.register('post', views.PostViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

 

 

APIView

models.py

from django.db import models

# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()

serializer.py

from .models import Post
from rest_framework import serializers

# serializers의 Serializers는 Django의 Form과 유사한 역할을 한다

# serializer의 ModelSerializer는 Django의 ModelForm과 유사한 역할을 한다

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        # fields = '__all__'
        fields = ('id', 'title', 'body') # id는 pk값
        read_only_fields = ('title',) # 리스트도 가능하지만 튜플 사용을 권장함

views.py

# 데이터 처리 대상
from .models import Post
from .serializer import PostSerializer
# status에 따라 직접 Response를 처리할 것
from django.http import Http404 # Get object of 404 직접 구현
from rest_framework.response import Response
from rest_framework import status
# APIView를 상속받은 CBV
from rest_framework.views import APIView
# PostDetail 클래스의 get_object 메소드 대신 아래 코드를 써도 된다.
# from django.shortcuts import get_object_or_404

class PostList(APIView):
    def get(self, request):
        posts = Post.objects.all()
        serializer = PostSerializer(posts, many=True) # 다수의 쿼리셋 객체 넘기기 (many=True)
        return Response(serializer.data) # 직접 Response 리턴해주기 : serializer.data

    def post(self, request):
        serializer = PostSerializer(data=request.data)
        if serializer.is_valid(): # 직접 유효성 검사
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # Response(data, status)

# PostList 클래스와는 달리 pk값을 받음 (메소드에 pk인자)
class PostDetail(APIView):
    # get_object_or_404를 구현해주는 helper function
    def get_object(self, pk):
        try:
            return Post.objects.get(pk=pk)
        except Post.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        post = self.get_object(pk)
        # post = get_object_or_404(Post, pk)
        serializer = PostSerializer(post)
        return Response(serializer.data)

    # 위 post 메소드와 비슷한 논리
    def put(self, request, pk, format=None):
        post = self.get_object(pk)
        serializer = PostSerializer(post, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        post = self.get_object(pk)
        post.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

urls.py

from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

# Default Router 사용 X ==> API ROOT 없음

urlpatterns = [
    # 127.0.0.1:8000/post == ListView
    path('post/', views.PostList.as_view()),
    # 127.0.0.1:8000/post/<pk> == DetailtView
    path('post/<int:pk>', views.PostDetail.as_view),
]

urlpatterns = format_suffix_patterns(urlpatterns)

 

 

Mixins

views.py

from .models import Post
from .serializer import PostSerializer
from rest_framework import mixins
from rest_framework import generics

class PostList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    # queryset과 serializer_class 는 generics.GenericAPIView에서 이미 선언된 클래스 변수이다.
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs) # list는 mixins.ListModelMixin에서 이미 정의된 메소드이다.

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs) # create는 mixins.CreateModelMixin에서 이미 정의된 메소드이다.

class PostDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    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)

urls.py

from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

# Default Router 사용 X ==> API ROOT 없음

urlpatterns = [
    # 127.0.0.1:8000/post == ListView
    path('post/', views.PostList.as_view()),
    # 127.0.0.1:8000/post/<pk> == DetailtView
    path('post/<int:pk>', views.PostDetail.as_view),
]

urlpatterns = format_suffix_patterns(urlpatterns)

 

Generic CBV

views.py

from .models import Post
from .serializer import PostSerializer
from rest_framework import generics

class PostList(generics.ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

class PostDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

urls.py

from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

# Default Router 사용 X ==> API ROOT 없음

urlpatterns = [
    # 127.0.0.1:8000/post == ListView
    path('post/', views.PostList.as_view()),
    # 127.0.0.1:8000/post/<pk> == DetailtView
    path('post/<int:pk>', views.PostDetail.as_view),
]

urlpatterns = format_suffix_patterns(urlpatterns)

 

APIView

views.py

# ReadOnlyModelViewSet
from .models import Post
from .serializer import PostSerializer
from rest_framework import viewsets

class PostViewSet(viewsets.ReadOnlyModelViewSet):
    """
    This viewset automatically provides `list` and `detail` actions.
    """
    queryset = Post.objects.all()
    serializer_class = PostSerializer
# ModelViewSet
from .models import Post
from .serializer import PostSerializer
from rest_framework import viewsets
# @action 처리
from rest_framework import renderers
from rest_framework.decorators import action
from django.http import HttpResponse

class PostViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.

    Additionally we also provide an extra `highlight` action.
    """
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    
    # 권한 설정
    # permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
    
    # @ + 함수 → decorator(장식자)
    # @action : Custom API 만들기(임의로 View 설계)
    # @action(method=['post'])
    # Custom API의 Default Method는 GET 방식이지만, action의 format 인자로 지정 가능하다.
    # renderer_classes는 Response를 어떤 형식으로 Rendering 시킬 것인가
    @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer]) 
    def highlight(self, request, *args, **kwargs):
        return HttpResponse("얍")

urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

# django rest framework -> router -> url

router = DefaultRouter()
router.register('post', views.PostViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

path()를 묶어주는 .as_view()

 

 

참고 : django-rest-framework github

 

encode/django-rest-framework

Web APIs for Django. 🎸. Contribute to encode/django-rest-framework development by creating an account on GitHub.

github.com

참고 : django-rest-framework documentation

 

Home - Django REST framework

 

www.django-rest-framework.org

 

'Server > django' 카테고리의 다른 글

[Django] Filtering & Search  (0) 2020.05.25
[Django] Pagination  (0) 2020.05.25
[Django] JSON 직렬화 - Serializer  (0) 2020.04.28
[Django] REST Architecture  (0) 2020.04.28
[Django] JSON, Http Request & Method, Httpie  (0) 2020.04.23