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請求新增單條資料,資料新增成功