基於上篇隨筆的表結構,經過序列化組件的ModelSerializer設計以下三個接口:python
GET 127.0.0.1:8000/books/{id} # 獲取一條數據,返回值:{} PUT 127.0.0.1:8000/books/{id} # 修改數據,返回值:{} DELETE 127.0.0.1:8000/books/{id} # 刪除數據,返回空
urls.py文件:程序員
from django.urls import path, re_path from serializer import views urlpatterns = [ re_path('books/(\d+)/$', views.BookFilterView.as_view()) ]
Views.py文件:django
class BookFilterView(APIView): def get(self, request, nid): book_obj = Book.objects.get(pk=nid) serialized_data = BookSerializer(book_obj, many=False) return Response(serialized_data.data) def put(self, request, nid): book_obj = Book.objects.get(pk=nid) verified_data = BookSerializer(data=request.data, instance=book_obj, many=False) if verified_data.is_valid(): verified_data.save() return Response(verified_data.data) else: return Response(verified_data.errors) def delete(self, request, nid): Book.objects.get(pk=nid).delete() return Response()
前面的介紹中,咱們已經經過序列化組件設計除了符合REST規範的五個經常使用接口,如今假設,咱們有多個數據接口,好比(Book,Author,Publish...)等數據表都須要定義相似的接口,能夠預見,咱們須要重複定義相似上面的五個接口,這種方式將會致使大量的重複代碼,顯然,咱們的程序還有不少須要優化的地方,那麼,若是是你,將會如何進行優化呢?編程
首先回顧如下混入類和多繼承的知識,有以下一個Animal類:網絡
class Animal(object): def eat(self): print("Eating") def sleepping(self): print("sleepping")
class Bird(Animal): def flying(self): print("flying") class Bee(Animal): def flying(self): print("flying")
此時,咱們能夠改成以下代碼(python支持多繼承,不是全部語言都有這個特色):app
class Animal(object): def eat(self): print("Eating") def sleepping(self): print("sleepping") class Flying(object): def flying(self): print("flying") class Bird(Animal, Flying): pass class Bee(Animal, Flying): pass
看到這裏,結合上面的回顧的混合類和多繼承,咱們是否可使用下面的方式優化以前的接口設計呢?socket
class GetAllData(): def get(self, request):pass class GetOneData(): def get(self, request):pass class DeleteOneData(): def delete(self, request):pass class UpdateOneData(): def put(self, request):pass class CreateData(): def post(self, request):pass class BookView(APIView, GetAllData, CreateData):pass class BookFilterView(APIView, GetOneData, DeleteOneData, UpdateOneData):pass
像上面代碼這樣,將每一個接口都寫到獨立的類中,而後使用多繼承,或者成爲mixin的這種方式,就能夠對咱們的程序進行優化,mixin的方式很是常見,在網絡編程中學過的socketserver,其源碼中就有對mixin的實現,即,假設咱們須要進程的時候,咱們繼承進程類,若是咱們須要線程的時候,咱們就繼承線程類便可。post
視圖組件是用來優化接口邏輯的。性能
一、使用視圖組件的mixin進行接口邏輯優化,上面五個接口能夠改寫以下:優化
urls.py代碼:
from django.urls import re_path from serializer import views urlpatterns = [ re_path('books/$', views.BookView.as_view()), re_path('books/(?P<pk>\d+)/$', views.BookFilterView.as_view()), ]
視圖views.py代碼:
from rest_framework.mixins import ( ListModelMixin, CreateModelMixin, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin ) from rest_framework.generics import GenericAPIView from rest_framework.response import Response # 導入序列化類 from .app_serializers import BookSerializer from .models import Book, Publish, Author class BookView(ListModelMixin, CreateModelMixin, GenericAPIView): # queryset和serializer_class是固定寫法 queryset = Book.objects.all() serializer_class = BookSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class BookFilterView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView): queryset = Book.objects.all() serializer_class = BookSerializer 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)
注意:單條數據操做的url有變化,由於咱們在視圖中,統一傳的都是queryset,因此,須要經過傳入一個名爲pk的命名參數,告訴視圖組件,用戶須要操做的具體數據。
二、使用視圖組件的genericview進行接口邏輯優化
上面的代碼看似已經優化的很是完美了,可是,在一個對性能要求極高的項目裏面,咱們的程序還能夠繼續優化,不斷優化程序是每一個程序員必備的技能,也是幫助咱們成長的重要手段。一樣的思路,一樣的方法,咱們能夠將多個接口封裝到一個功能類中,以下代碼:
from rest_framework import generics from .app_serializers import BookSerializer from .models import Book, Publish, Author class BookView(generics.ListCreateAPIView): queryset = Book.objects.all() serializer_class = BookSerializer class BookFilterView(generics.RetrieveUpdateDestroyAPIView): queryset = Book.objects.all() serializer_class = BookSerializer
三、使用視圖組件的viewset進行接口邏輯優化
上面的代碼已經看似很是完美了,可是,你有沒有發現還有重複代碼,該如何改進呢?使用viewset能夠進一步優化,以下:
urls.py文件(注意跟以前有什麼不一樣):
from django.urls import re_path from serializer import views urlpatterns = [ re_path('books/$', views.BookView.as_view({ 'get': 'list', 'post': 'create' })), re_path('books/(?P<pk>\d+)/$', views.BookView.as_view({ 'get': 'retrieve', 'put': 'update', 'delete': 'destroy' }))
視圖views.py部分:
from rest_framework.viewsets import ModelViewSet from .app_serializers import BookSerializer from .models import Book, Publish, Author class BookView(ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer
使用方式是否是很簡單,接下來去看如下源碼都爲咱們作了什麼吧!其實整個viewset優化方案最重要的地方就是urls.py中傳入了參數,而後對參數進行映射關係綁定。