- RESTful 規范
- django rest framework 之 認證(一)
- django rest framework 之 權限(二)
- django rest framework 之 節流(三)
- django rest framework 之 版本(四)
- django rest framework 之 解析器(五)
- django rest framework 之 序列化(六)
- django rest framework 之 分頁(七)
- django rest framework 之 視圖(八)
在之前的django rest framework其他組件中,在視圖函數中繼承類都是rest_framework.view.APIView,這個APIView是繼承的django中的View並且做了封裝和方法重寫的。 那么在django rest framework中,還有有沒有提供其他的類能夠繼承?
一、GenericAPIView
GenericAPIView在django rest framework中根據APIView又做了一層封裝。則繼承關系就變成了GenericAPIView——>APIView——>View
from rest_framework.generics import GenericAPIView
class GenericView(GenericAPIView):
queryset = Role.objects.get_queryset().order_by('id')
serializer_class = PagerSerializer
pagination_class = PageNumberPagination
def get(self,request,*args,**kwargs):
roles = self.get_queryset()
pager_roles = self.paginate_queryset(roles)
ser = self.get_serializer(instance=pager_roles,many=True)
return Response(ser.data)
這里實現的功能和django rest framework 之 分頁中的功能一樣,先獲取數據,分頁,序列化返回。不同的是,這里由於封裝的作用,GenericAPIView的內部的一些方法會根據會自動的獲取數據庫查詢結果並分頁和序列化。
- get_queryset(): 會獲取數據庫查詢結果,也就是
queryset - paginate_queryset(roles):會根據重寫的
pagination_class屬性獲取分頁類進行分頁操作,另外如果這里沒有重寫,會自動到settings.py配置文件去找 - self.get_serializer():就是根據分頁后的對象進行數據的序列化,也會先找到序列化類
二、GenericViewSet
1、源碼分析
GenericViewSet實際上使用了多繼承和Mixin模式,也就是說GenericViewSet同時繼承了ViewSetMixin, generics.GenericAPIView兩個父類
# rest_framework\viewsets.py 源碼
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
pass
在GenericViewSet中由於類繼承的先后順序的關系,會先執行ViewSetMixin類中相關方法。而GenericAPIView類中的相關方法會被忽略。
2、路由
在執行之前要更改一下路由系統
from django.conf.urls import url
from .views import *
app_name = 'api'
urlpatterns = [
url(r'^generic/$', GenericView.as_view()),
url(r'^genericset/$', GenericSetView.as_view({'get': 'list', 'post': 'create'})),
]
由於在GenericViewSet的內部重寫了as_view方法,且繼承關系又先於GenericAPIView類,所以會進入GenericViewSet的as_view方法。但是在as_view方法中,對路由系統做了略微的改動,需要對方法,做一一映射關系。即'get': 'list', 'post': 'create',get(獲取單條數據)請求,會進入子類的list方法,而create(創建對象)方法則代表了post請求。
3、視圖
視圖中基本上和上面一樣,只不過更改了不同http請求方法的對應類方法名
from rest_framework.viewsets import GenericViewSet
class GenericSetView(GenericViewSet):
queryset = Role.objects.get_queryset().order_by('id')
serializer_class = PagerSerializer
pagination_class = PageNumberPagination
def list(self,request,*args,**kwargs):
# 獲取數據
roles = self.get_queryset() # models.Role.objects.all()
# [1, 1000,] [1,10]
pager_roles = self.paginate_queryset(roles)
# 序列化
ser = self.get_serializer(instance=pager_roles,many=True)
return Response(ser.data)
def create(self, request, *args, **kwargs):
ret = {}
try:
title = request.data['title']
Role.objects.create(title=title)
print('success')
except Exception as e:
print(e)
4、測試
<1>、測試一
http://127.0.0.1:8000/api/genericset,get方法獲取數據時,返回正常結果

<2>、測試二
http://127.0.0.1:8000/api/genericset/,表示發送post請求添加單條數據,數據添加成功


三、ModelSetView
1、源碼分析
ModelSetView做的更徹底,他又一次繼承了GenericViewSet,並且在此之前又繼承了其他幾個類,因此功能更多,變成了ModelViewSet——>GenericViewSet——>APIView——>View
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
pass
從這些類的名字可以大概看出,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,.ListModelMixin,分別對應,創建,獲取單條數據,更新,刪除,或許多條數據。
2、路由
from django.conf.urls import url
from django.urls import path
from .views import *
app_name = 'api'
urlpatterns = [
url(r'^modelset/(?P<pk>\d+)/$', ModelSetView.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
]
由於在獲取,刪除,更新數據的時候需要這頂數據的唯一標識,這里是pk主鍵,因此需要在url中增加正則匹配。
3、視圖
在視圖中,並沒有增加相應的增刪改查的邏輯卻能完成相應的功能,這是因為繼承的mixin類中,已經有一一對應的方法,視圖類會自動調用父類的方法。
from rest_framework.viewsets import ModelViewSet
class ModelSetView(ModelViewSet):
queryset = Role.objects.get_queryset().order_by('id')
serializer_class = PagerSerializer
pagination_class = PageNumberPagination
獲取第九條數據,返回結果

4、自定義
在ModelSetView中看到,繼承了多個mixin類,而這些類又分別封裝了不同的對應於增刪給查的方法,因此如果想要自定義一個接口,實現部分http方法,就可以根據需要繼承不同的mixin類
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
