drf4 視圖與路由組件

APIView和View的區別

無論是View仍是APIView最開始調用的都是as_view()django

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

 

在View中的as_view方法返回了view函數,而view函數執行了self.dispatch()方法,可是這裏的dispatch方法應該是咱們APIView中的ide

 

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

 

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

 

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

 

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

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

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

相比原來的django的request,咱們如今的request更加精簡,清晰了code

如今咱們知道了APIView和View的一些區別

 

視圖的第一次封裝

 

GenericAPIView 是對 APIView 的封裝 
xxxMixin  是對處理的各類請求方法的封裝
 
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("刪除的書籍不存在")

APIView視圖
APIView
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from .serializers import BookSerializer




class GenericAPIView(APIView):
    query_set = None
    serializer_class = None

    def get_queryset(self):
        return self.query_set

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)


class ListModelMixin(object):
    def list(self, request):
        queryset = self.get_queryset()
        ret = self.get_serializer(queryset, many=True)
        return Response(ret.data)


class CreateModelMixin(object):
    def create(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)


class RetrieveModelMixin(object):
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ret = self.get_serializer(book_obj)
        return Response(ret.data)


class UpdateModelMixin(object):
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        serializer = self.get_serializer(book_obj, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)


class DestroyModelMixin(object):
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        book_obj.delete()
        return Response("")


class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass


# class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
class BookView(ListCreateAPIView):
    query_set = Book.objects.all()      # 操做的表的對象
    serializer_class = BookSerializer   # 序列化的類

    def get(self, request):
        # book_obj = Book.objects.first()
        # ret = BookSerializer(book_obj)
        # book_list = Book.objects.all()
        # book_list = self.get_queryset()
        # ret = self.get_serializer(book_list, many=True)
        # return Response(ret.data)
        return self.list(request)

    def post(self, request):
        # print(request.data)
        # serializer = BookSerializer(data=request.data)
        # if serializer.is_valid():
        #     serializer.save()
        #     return Response(serializer.data)
        # else:
        #     return Response(serializer.errors)
        return self.create(request)


# class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
class BookEditView(RetrieveUpdateDestroyAPIView):
    query_set = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id):
        # book_obj = Book.objects.filter(id=id).first()
        # ret = BookSerializer(book_obj)
        # return Response(ret.data)
        return self.retrieve(request, id)

    def put(self, request, id):
        # book_obj = Book.objects.filter(id=id).first()
        # serializer = BookSerializer(book_obj, data=request.data, partial=True)
        # if serializer.is_valid():
        #     serializer.save()
        #     return Response(serializer.data)
        # else:
        #     return Response(serializer.errors)
        return self.update(request, id)

    def delete(self, request, id):
        # book_obj = Book.objects.filter(id=id).first()
        # book_obj.delete()
        # return Response("")
        return self.destroy(request, id)
視圖的第一次封裝

 

 

視圖的第二次封裝

 

class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass

class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass

class BookView(ListCreateAPIView):
    pass

class BookEditView(RetrieveUpdateDestroyAPIView):
    pass
# 上面咱們寫的繼承類太長了~~咱們再改改

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)

第二次封裝
第二次封裝

視圖的第三次封裝

 

ViewSetMixin

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

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

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

由於是按照請求的方式不一樣反回的結果,全部第二次有兩個視圖函數

 

如今指定一個視圖函數

  # 視圖類傳參,不一樣的請求對應不一樣的方法
    path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
    path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

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

# class ViewSetMixin(object):
#     def as_view(self):
#         """
#         按照咱們參數指定的去匹配 對應的方法
#         get-->list
#         :return: 不用咱們去寫,框架有
#         """

 

ViewSetMixin 請求分發方法的原理,將不一樣的請求設置爲不一樣的方法

 

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

第三次封裝
第三次封裝
from rest_framework.viewsets import ViewSetMixin

class ModelViewSet(ViewSetMixin, GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass

# from rest_framework.viewsets import ModelViewSet
#  框架內部已經實現了的,能夠直接導入
#
class BookModelViewSet(ModelViewSet):
    
    query_set = Book.objects.all() 本身封裝的query_set
  # queryset = Book.objects.all() # 框架的是queryset
serializer_class = BookSerializer
 
 
 
 
 
 
 
 
from rest_framework import views     # APIView
from rest_framework import generics # GenericAPIView, 組合類
from rest_framework import mixins #混合繼承類
from rest_framework import viewsets # ViewSetMixin 分發請求的類

 

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

 

 

image

用框架的時

路由爲

 path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

 

前面本身定義的是id,用框架時注意修改過來

 path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

 

 # 視圖類傳參.只有業務需求匹配性很強才用。一般狀況下不這麼用容易暴露接口
 # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
 # path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

繼承順序

 

DRF的路由

 

from django.urls import path, include
from .views import BookView, BookEditView, BookModelViewSet
from rest_framework.routers import DefaultRouter


router = DefaultRouter()

router.register(r"", BookModelViewSet)  # 不能 加$ r"$"


urlpatterns = [
    # path('list', BookView.as_view()),
    # path('retrieve/<int:id>', BookEditView.as_view()),


    # 視圖類傳參.只有業務需求匹配性很強才用。一般狀況下不這麼用容易暴露接口
    # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
    # path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

]


urlpatterns += router.urls

DefaultRouter
DRF的路由

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

當不須要那麼多路由的時候,也不要用這種路由註冊

總之,一切按照業務須要去用

相關文章
相關標籤/搜索