rest framework 視圖,路由

 視圖

  在上面序列化的組件種已經用到了視圖組件,即在視圖函數部分進行邏輯操做。數據庫

  可是很明顯的弊端是,對每一個表的增刪改查加上 單條數據,須要用到 2個類 5個方法(增刪改查,單數據查)才能夠完整的實現,當表的數量較大的時候,就很蠢了。django

  所以 rest framework 也對這個進行了多層的封裝。json

源碼位置 

rest_framework.viewsets  
rest_framework.generics  
rest_framework.mixins 

最底層的三個基礎文件

rest_framework.viewsets

# 內部提供了 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):...

rest_framework.generics

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):

 rest_framework.mixins 

    內置的操做方法 增刪改查 單行數據查詢都在這裏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 的基礎上 又得到了 增刪改查方法的集成 函數

最初始最全面也是最笨的方式操做表

方式1 2類5方法無判斷

對於所有數據的查詢以及數據的建立不須要帶參數,設計爲一條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()

方式2 一類5方法帶判斷

只寫一個類,內含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__"
相關文章
相關標籤/搜索