天天看點

Django RESTful API (3) 基于類的視圖

歡迎關注個人微信公衆号,大大大碗面,不定期分享AI論文解讀和開發技術,網際網路小白,輕噴~

Django RESTful API (3) 基于類的視圖

改為基于類的視圖

重構一下snippets/view.py:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class SnippetList(APIView):
    """
    列出所有已經存在的snippet或者建立一個新的snippet
    """
    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(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)
           

到這裡應該很容易了解,和原來的相比,可以發現基于類的視圖把各種不同的HTTP請求分離開變成單個的方法,而不是

if...elif...

這樣的結構,是以這樣處理起來很更加的高效。

同樣的,把另一個視圖函數

snippet_detail

也進行修改:

class SnippetDetail(APIView):
    """
    檢索檢視、更新或者删除一個snippet
    """
    def get_object(self, pk):
        try:
            return Snippet.objects.get(pk=pk)
        except Snippet.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerializer(snippet, 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):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
           

改為基于類的視圖之後,當然也要修改一下路由了,對 snippets/urls.py 稍加修改:

from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)
           

這樣就可以運作程式了,功能和之前的是一樣的

使用mixins類

使用基于類的視圖的好處除了上面所說的把各種HTTP請求分離開,還有什麼好處嗎?答案是肯定的——使用基于類的視圖的最大優勢之一是它可以輕松地構成可重複使用的行為。

可重複使用的行為?簡單說,就是讓我們少寫一點功能類似的代碼,由此就要介紹一下mixins類了,它幫我們封裝了很多操作,簡化代碼,使用也很簡單,編輯snippets/view.py函數:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics

class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
           

新的視圖類中繼承了 generic.GenericAPIView、mixins.ListModelMixin 和 mixins.CreatteModelMixin,類的作用看字面意思就能懂啦,mixins類為我們提供了list()和create()方法,當然,使用這兩個函數需要先設定queryset和serializer_class,這點我們檢視一下mixins的源碼就可以看出來了,比如list方法:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
           

這裡的代碼會分别通過 get_queryset() 和 get_serializer() 得到查詢集和序列化器,其他封裝好的方法也是如此。

知道了這個,在修改一下另一個視圖類就很容易了:

class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    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)
           

使用通用視圖

到這裡,視圖代碼已經簡化了很多了,但是其實還可以進一步簡化:

進一步簡化就是連mixins類都不用了,隻使用generics就可以了,代碼如下:

from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

           

測試

Django RESTful API (3) 基于類的視圖