Django編寫RESTful API(三):基於類的視圖


歡迎訪問我的個人網站:www.comingnext.cn

前言

在上一篇文章中,主要講的是請求和響應,項目里面views.py中的視圖函數都是基於函數的,並且我們介紹了@api_view這個很有用的裝飾器。同時,我們還介紹了APIView這個類,但是還沒使用它。在這篇文章中,我們要做的是把基於方法的視圖改為基於類的視圖,將會了解到APIView。


改為基於類的視圖

重構一下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...這樣的結構,所以這樣處理起來很更加的高效。

同樣的,把另一個視圖函數也進行修改:

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)

 


使用通用的視圖類

到這里,視圖代碼已經簡化了許多了,但是我要告訴你的是,還可以進一步簡化。。。在此,讓我們一起在心中默念:

人生苦短,我用Python

進一步簡化就是連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

 

好了,現在的代碼就顯得非常簡潔了,但是短小卻精悍,依然可以實現原本的功能,隨意的展示一下: 

 


把基於函數的視圖改成基於類的視圖就講到這里了,下一篇文章會介紹授權和權限~

本文地址:http://www.cnblogs.com/zivwong/p/7434523.html
作者博客:ziv
歡迎轉載,請在明顯位置給出出處及鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM