歡迎訪問我的個人網站: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
歡迎轉載,請在明顯位置給出出處及鏈接