在上面序列化的組件種已經用到了視圖組件,即在視圖函數部分進行邏輯操做。數據庫
可是很明顯的弊端是,對每一個表的增刪改查加上 單條數據,須要用到 2個類 5個方法(增刪改查,單數據查)才能夠完整的實現,當表的數量較大的時候,就很蠢了。django
所以 rest framework 也對這個進行了多層的封裝。json
rest_framework.viewsets
rest_framework.generics
rest_framework.mixins
# 內部提供了 as_view 方法 class ViewSetMixin(object): # 此方法提供了 as_view 方法能夠加參數的條件 def as_view(cls, actions=None, **initkwargs):... # 用做總的繼承類 class GenericViewSet(ViewSetMixin, generics.GenericAPIView): ... # 單數據分支繼承類 ,只有全數據和單數據的查看方法 class ReadOnlyModelViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet):... # 全數據分支繼承類,最全內置增刪改查 以及 單數據查看方法 5個全都有 class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet):...
class GenericAPIView(views.APIView): # queryset 數據對象傳入用變量 queryset = None # 在視圖中序列化工具對象傳入用變量 serializer_class = None # 如下是一些增刪改查的各類共功能組合 ,用於繼承類使用 class CreateAPIView(mixins.CreateModelMixin, GenericAPIView):
class ListAPIView(mixins.ListModelMixin, GenericAPIView):
class RetrieveAPIView(mixins.RetrieveModelMixin, GenericAPIView):
class DestroyAPIView(mixins.DestroyModelMixin, GenericAPIView):
class UpdateAPIView(mixins.UpdateModelMixin, GenericAPIView):
class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView):
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericAPIView):
class RetrieveDestroyAPIView(mixins.RetrieveModelMixin, mixins.DestroyModelMixin, GenericAPIView):
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, GenericAPIView):
內置的操做方法 增刪改查 單行數據查詢都在這裏api
class CreateModelMixin(object): ... class ListModelMixin(object): ... class RetrieveModelMixin(object): ... class UpdateModelMixin(object): ... class DestroyModelMixin(object): ...
GenrericViewSet 封裝了 GenericAPIView 和 ViewSetMixin ,因而得到了 傳入對象以及 重寫 as_view 的功能app
ModelViewSet 封裝了 GenrericViewSet 和 mixins ,在 GenrericViewSet 的基礎上 又得到了 增刪改查方法的集成 函數
對於所有數據的查詢以及數據的建立不須要帶參數,設計爲一條URL工具
其餘單數據的查看編輯和刪除在設計一條URLpost
兩條URL 分別對應兩個類 url
所有的內容:spa
寫全了就是 2個類 ,加起來一共5方法
class BookView(APIView): def get(self,request): # 對全部數據進行查看 book_list=Book.objects.all() bs=BookModelSerializers(book_list,many=True,context={'request': request}) return Response(bs.data) def post(self,request): # 對數據進行建立提交 # post請求的數據 bs=BookModelSerializers(data=request.data) if bs.is_valid(): print(bs.validated_data) bs.save() # .create()方法 return Response(bs.data) else: return Response(bs.errors) class BookDetailView(APIView): def get(self,request,id): # 對單條數據進行查看 book=Book.objects.filter(pk=id).first() bs=BookModelSerializers(book,context={'request': request}) return Response(bs.data) def put(self,request,id): # 對單條數據進行更新 book=Book.objects.filter(pk=id).first() bs=BookModelSerializers(book,data=request.data) if bs.is_valid(): bs.save() # .updata() return Response(bs.data) else: return Response(bs.errors) def delete(self,request,id): # 刪除數據 Book.objects.filter(pk=id).delete() return Response()
只寫一個類,內含5方法,在get 的時候進行一次判斷便可
class IndexView(views.APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: pass # 獲取單條信息 else: pass # 獲取列表信息 def post(self,request,*args,**kwargs): pass def put(self,request,*args,**kwargs): pass def patch(self,request,*args,**kwargs): pass def delete(self,request,*args,**kwargs): pass
class SchoolView(APIView): def get(self, request, *args, **kwargs): query_set = models.School.objects.all() ser_obj = app01_serializers.SchoolSerializer(query_set, many=True) return Response(ser_obj.data) class SchoolDetail(APIView): def get(self, request, pk, *args, **kwargs): obj = models.School.objects.filter(pk=pk).first() ser_obj = app01_serializers.SchoolSerializer(obj) return Response(ser_obj.data)
利用GenericeAPIView 傳入 queryset對象以及 序列化對象, 再利用內置的 mixins 中的操做方法省去操做代碼
from rest_framework.generics import GenericAPIView from rest_framework import.mixins class SchoolView(GenericAPIView, mixins.ListModelMixin): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) class SchoolDetail(GenericAPIView, mixins.RetrieveModelMixin, mixins.CreateModelMixin): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer def get(self, request, pk, *args, **kwargs): return self.retrieve(request, pk, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
路由依舊是分紅兩條,單數據和多數據分開
url(r'school/$', views.SchoolView.as_view()), url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
利用GenericeAPIView 傳入 queryset對象以及 序列化對象, 再利用內置的 generics 中的操做方法省去操做代碼
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView class SchoolView(ListCreateAPIView): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer class SchoolDetail(RetrieveUpdateDestroyAPIView): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer
路由依舊是分紅兩條,單數據和多數據分開,同第一次整合無區別
url(r'school/$', views.SchoolView.as_view()),
url(r'school/(?P<pk>\d+)/$', views.SchoolDetail.as_view()),
直接繼承最終的 ModelViewSet 繼承類 ,ModelViewSet 在 ViewSetMixin 類 之上,能夠重寫 as_view 方法可以添加參數
from rest_framework.viewset import ModelViewSet class SchoolView(ModelViewSet): queryset = models.School.objects.all() serializer_class = app01_serializers.SchoolSerializer
由於視圖被極大的壓縮,參數的傳遞交給了 as_view 來處理,所以 url 會變得比以往復雜,url 還能夠進一步封裝,詳情往下看路由部分
url(r'school/$', views.SchoolView.as_view({ "get": "list", "post": "create", })), url(r'school/(?P<pk>\d+)/$', views.SchoolView.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy' })),
class P2(PageNumberPagination): page_size = 3 #每一頁顯示的條數 page_query_param = 'page' #獲取參數中傳入的頁碼 page_size_query_param = 'size' #獲取url參數中每頁顯示的數據條數 max_page_size = 5 class IndexSerializer(ModelSerializer): class Meta: model = models.UserInfo fields = "__all__" class IndexView4(ModelViewSet): queryset = models.UserInfo.objects.all() serializer_class = IndexSerializer pagination_class = P2 def list(self, request, *args, **kwargs): '''獲取get請求的全部''' pass def retrieve(self, request, *args, **kwargs): '''查看單條數據''' pass def destroy(self, request, *args, **kwargs): '''刪除DELETE''' pass def create(self, request, *args, **kwargs): '''添加數據POST''' pass def update(self, request, *args, **kwargs): '''所有修改PUT''' pass def partial_update(self, request, *args, **kwargs): '''局部修改PATCH''' pass
二次整理版本( 濃縮版 )
""" 繼承結構 (功能↓) (封裝↑) ModelViewSet/ReadOnlyModelViewSet generics.xxx GenericViewSet mixins.xxx GenericAPIView APIView ViewSetMixin 基礎的四個功能組件(每一個都有本身獨有功能) APIView(View) 啥都沒有, 所有手寫去吧 ViewSetMixin(object) 提供了 as_view 的重寫 以及 initialize_request 裏面不少的 action mixins.xxx(object) 提供如下的 5 個基礎的增刪改查方法, CreateModelMixin - create() post() ListModelMixin - list() get() RetrieveModelMixin - retrieve() patch() DestroyModelMixin - destroy() delete() UpdateModelMixin - update() put() GenericAPIView(views.APIView) 提供瞭如下字段的封裝, 不須要手寫了 queryset = None 數據庫對象 serializer_class = None 序列化對象 lookup_field = 'pk' 默認查詢字段, 默認是 id lookup_url_kwarg = None 查詢單一數據時URL中的參數關鍵字名稱, 默認與look_field相同 filter_backends = api_settings.DEFAULT_FILTER_BACKENDS 過濾 pagination_class = api_settings.DEFAULT_PAGINATION_CLASS 分頁器選擇 進階的兩個(對基礎組件的一層封裝) GenericViewSet(ViewSetMixin, generics.GenericAPIView) 集合了 as_view 以及 可寫參數 generics.xxxx.....(mixins.xxxxx,GenericAPIView) 各式的組合增刪改查, 以及附加參數功能 CreateAPIView(mixins.CreateModelMixin,GenericAPIView) ListAPIView(mixins.ListModelMixin,GenericAPIView) RetrieveAPIView(mixins.RetrieveModelMixin,GenericAPIView) DestroyAPIView(mixins.DestroyModelMixin,GenericAPIView) UpdateAPIView(mixins.UpdateModelMixin,GenericAPIView) ListCreateAPIView(mixins.ListModelMixin,mixins.CreateModelMixin,GenericAPIView) RetrieveUpdateAPIView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,GenericAPIView) RetrieveDestroyAPIView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,GenericAPIView) RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,GenericAPIView) 終極的兩個(二級封裝更加方便了) ReadOnlyModelViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet) 其餘都有, 只能讀取 ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet) 所有都有, 集合了全部的請求方式 視圖繼承的選擇 一階段 View 你這是在用 django 二階段 APIView 在用 drf 了.可是是最基礎的方式 三階段 GenericAPIView 不少參數能夠用了, 可是全部方法本身寫 四階段 GenericAPIView + mixins 能用參數了, 不用寫各請求的邏輯了. 可是還要寫個殼子 五階段 GenericAPIView + generics.xxx 能用參數, 並且靈活組合本身的請求類型, 殼子也不用寫了 六階段 GenericViewSet + generics.xxx 能用參數, 靈活組請求類型, 重寫了as_view, 得到高級路由功能 七階段 ReadOnlyModelViewSet 前面有的我都有. 可是我只能讀 八階段 ModelViewSet 我全都有 """
單數據,全數據的兩隻路由加 帶格式的兩隻路由一共4條路由
# http://127.0.0.1:8000/api/v1/auth/ url(r'^auth/$', views.AuthView.as_view()),
# http://127.0.0.1:8000/api/v1/auth.json # 想要讓頁面顯示json格式 url(r'^auth\.(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),
# http://127.0.0.1:8000/api/v1/auth/1/ url(r'^auth/(?P<pk>\d+)/$', views.AuthView.as_view()),
# http://127.0.0.1:8000/api/v1/auth/1.json url(r'^auth/(?P<pk>\d+)\.(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),
class AuthView(views.APIView): def get(self,request,*args,**kwargs): return Response('...')
重寫了 as_view 方法後,能夠在as_view方法中加入參數傳遞方法對應,手動指定響應方式和視圖方法的映射
url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})), url(r'^index\.(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'list','post':'create'})), url(r'^index/(?P<pk>\d+)/$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})), url(r'^index(?P<pk>\d+)\.(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})), class IndexView(viewsets.ModelViewSet): queryset = models.UserInfo.objects.all() serializer_class = IndexSerializer pagination_class = P2
徹底自動生成全部的 url,且自動建立了視圖關係
# 註冊前的準備,作一個實例化對象 routers=routers.DefaultRouter() # 註冊須要加兩個參數 ("url前綴",視圖函數) routers.register("authors",views.AuthorModelView) routers.register("books",views.AuthorModelView)
""" 會自動幫你生成 4 條 url ^authors/$ [name='author-list'] ^authors\.(?P<format>[a-z0-9]+)/?$ [name='author-list'] ^authors/(?P<pk>[^/.]+)/$ [name='author-detail'] ^authors/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='author-detail'] # 響應器控制 """ urlpatterns = [ # url(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"), # url(r'^authors/(?P<pk>\d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailauthor"), # 上面的兩條被簡化成了下面一句話 url(r'', include(routers.urls)), ]
router = DefaultRouter() router.register('index',views.IndexViewSet) urlpatterns = [ url(r'^', include(router.urls)), ] class IndexViewSet(viewsets.ModelViewSet): queryset = models.UserInfo.objects.all() serializer_class = IndexSerializer pagination_class = P2 class IndexSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"