無論是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視圖
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 分發請求的類
咱們如今的視圖就只要寫兩行就能夠了
用框架的時
路由爲
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"})),
繼承順序
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
經過框架咱們能夠把路由視圖都變的很是簡單,可是須要自定製的時候仍是須要咱們本身用APIView寫
當不須要那麼多路由的時候,也不要用這種路由註冊
總之,一切按照業務須要去用