django Rest Framework 視圖和路由

django Rest Framework 視圖和路由

DRF視圖

1. APIView

  • 咱們django中寫CBV的時候繼承的是View,rest_framework繼承的是APIView,那麼他們兩個有什麼不一樣呢~~~前端

    urlpatterns = [
        url(r'^book$', BookView.as_view()),
        url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
    ]
  1. 前端發來請求,根據正則匹配,而後調用APIView中的as_view()方法python

    img

    APIView繼承了View, 而且執行了View中的as_view()方法,最後把view返回了,用csrf_exempt()方法包裹後去掉了csrf的認證。django

  2. View中的as_view()方法作了api

    img

    看到self,要從最開始的類中開始看,而後再從父類中看,APIView中含有dispatch方法,全部要先看APIView中的框架

  3. 查看APIView中的dispatch方法iview

    img

    去initialize_request中看下把什麼賦值給了request,而且賦值給了self.request, 也就是咱們在視圖中用的request.xxx究竟是什麼~~函數

  4. 查看initialize_request方法post

    img

    這個方法返回的是Request這個類的實例對象~~咱們注意咱們看下這個Request類中的第一個參數request,是咱們走咱們django的時候的原來的request~url

  5. 點擊Request方法spa

    img

    Request類把原來的request賦值給了self._request, 也就是說之後_request是咱們老的request,新的request是咱們這個Request類~~

    即對request的功能進行的封裝,擴展

  6. 繼承APIView以後的數據在哪裏來的

    img

    咱們用了rest_framework框架之後,咱們的request是從新封裝的Request類~

    request.query_params 存放的是咱們get請求的參數

    request.data 存放的是咱們全部的數據,包括post請求的以及put,patch請求~~~

2. 第一次封裝

  • APIView視圖

    class BookView(APIView):
    
        def get(self, request):
            query_set = Book.objects.all()
            book_ser = BookSerializer(query_set, many=True)
            return Response(book_ser.data)
    
        def post(self, request):
            query_set = request.data
            book_ser = BookSerializer(data=query_set)
            if book_ser.is_valid():
                book_ser.save()
                return Response(book_ser.validated_data)
            else:
                return Response(book_ser.errors)
    
    
    class BookEditView(APIView):
    
        def get(self, request, id):
            query_set = Book.objects.filter(id=id).first()
            book_ser = BookSerializer(query_set)
            return Response(book_ser.data)
    
        def patch(self, request, id):
            query_set = Book.objects.filter(id=id).first()
            book_ser = BookSerializer(query_set, data=request.data, partial=True)
            if book_ser.is_valid():
                book_ser.save()
                return Response(book_ser.validated_data)
            else:
                return Response(book_ser.errors)
    
        def delete(self, request, id):
            query_set = Book.objects.filter(id=id).first()
            if query_set:
                query_set.delete()
                return Response("")
            else:
                return Response("刪除的書籍不存在")
  • 封裝

    class GenericAPIView(APIView):
        queryset = None
        serializer_class = None
    
        def get_queryset(self):
            return self.queryset.all()
    
        def get_serializer(self, *args, **kwargs):
            return self.serializer_class(*args, **kwargs)
    
    
    class ListModelMixin(object):
        def list(self, request, *args, **kwargs):
            queryset = self.get_queryset()
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    
    
    class CreateModelMixin(object):
        def create(self, request, *args, **kwargs):
            serializer = self.get_serializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.validated_data)
            else:
                return Response(serializer.errors)
    
    
    class RetrieveModelMixin(object):
        def retrieve(self, request, id, *args, **kwargs):
            book_obj = self.get_queryset().filter(pk=id).first()
            book_ser = self.get_serializer(book_obj)
            return Response(book_ser.data)
    
    
    class UpdateModelMixin(object):
        def update(self, request, id, *args, **kwargs):
            book_obj = self.get_queryset().filter(pk=id).first()
            book_ser = self.get_serializer(book_obj, data=request.data, partial=True)
            if book_ser.is_valid():
                book_ser.save()
                return Response(book_ser.validated_data)
            else:
                return Response(book_ser.errors)
    
    
    class DestroyModelMixin(object):
        def destroy(self, request, id, *args, **kwargs):
            queryset = self.get_queryset()
            try:
                queryset.get(pk=id).delete()
                return Response("")
            except Exception as e:
                return Response("信息有誤")
    # 咱們把公共的部分抽出來 這樣無論寫多少表的增刪改查都變的很簡單
    # 這樣封裝後咱們的視圖會變成這樣
    
    class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
        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 BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request, id, *args, **kwargs):
            return self.retrieve(request, id, *args, **kwargs)
    
        def patch(self, request, id, *args, **kwargs):
            return self.update(request, id, *args, **kwargs)
    
        def destroy(self, request, id, *args, **kwargs):
            return self.delete(request, id, *args, **kwargs)

    封裝的GenericAPIView,包括封裝每一個方法的類,其實框架都幫咱們封裝好了

3 第二次封裝

  • class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
        pass
    
    
    class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        pass
    
    
    class BookView(ListCreateAPIView):
        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 BookEditView(RetrieveUpdateDestroyAPIView):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
    
        def get(self, request, id, *args, **kwargs):
            return self.retrieve(request, id, *args, **kwargs)
    
        def patch(self, request, id, *args, **kwargs):
            return self.update(request, id, *args, **kwargs)
    
        def delete(self, request, id, *args, **kwargs):
            return self.delete(request, id, *args, **kwargs)

    此次咱們只是讓繼承變的簡單了一點而已,好像並無什麼大的進步~~

    內置源碼提供的方法

    img

    actions這個默認參數其實就是咱們路由能夠進行傳參了~~~

    下面這個循環~能夠看出~咱們要傳的參數是一個字段~key應該是咱們的請求方式,value應該對應咱們處理的方法~

    這樣咱們每一個視圖就不用在寫函數了~由於已經和內部實現的函數相對應了~

4. 第三次封裝

  • 路由url.py

    urlpatterns = [
        # url(r'^book$', BookView.as_view()),
        # url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
        url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
        url(r'^book/(?P<pk>\d+)$', BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
    ]
  • view.py

    from rest_framework.viewsets import ViewSetMixin
    
    
    # class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
    #     queryset = Book.objects.all()
    #     serializer_class = BookSerializer
    
    
    # 若是咱們再定義一個類
    class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
        pass
    
    
    class BookView(ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookSerializer

    咱們如今的視圖就只要寫兩行就能夠了~~~

    其實咱們寫的全部的視圖~框架都幫咱們封裝好了~

    注意一點:用框架封裝的視圖~咱們url上的那個關鍵字參數要用pk 系統默認的~~

    奉獻一張圖來看下咱們的繼承順序

    img

DRF路由

  • 路由傳參寫的特別多~~框架也幫咱們封裝好了~

    from .views import BookView
    from rest_framework.routers import DefaultRouter
    
    router = DefaultRouter()
    router.register(r"book", BookView)
    
    urlpatterns = [
        # url(r'^book$', BookView.as_view()),
        # url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
        # url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
        # url(r'^book/(?P<pk>\d+)$', BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
    
    ]
    urlpatterns += router.urls

    經過框架咱們能夠把路由視圖變得很簡單,可是須要自定製的時候仍是須要本身用APIView寫,

    路由組件
      -- 導入 from rest_framework.routers import DefaultRouter
      -- 實例化 
          router = DefaultRouter()
      -- 註冊
          router.register('路由',View)
      -- 把自動生成的路由註冊
          urlpatterns += router.urls
相關文章
相關標籤/搜索