咱们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个有什么不一样呢~~~前端
urlpatterns = [ url(r'^book$', BookView.as_view()), url(r'^book/(?P<id>\d+)$', BookEditView.as_view()), ]
前端发来请求,根据正则匹配,而后调用APIView中的as_view()方法python
APIView继承了View, 而且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。django
View中的as_view()方法作了api
看到self,要从最开始的类中开始看,而后再从父类中看,APIView中含有dispatch方法,全部要先看APIView中的框架
查看APIView中的dispatch方法iview
去initialize_request中看下把什么赋值给了request,而且赋值给了self.request, 也就是咱们在视图中用的request.xxx究竟是什么~~函数
查看initialize_request方法post
这个方法返回的是Request这个类的实例对象~~咱们注意咱们看下这个Request类中的第一个参数request,是咱们走咱们django的时候的原来的request~url
点击Request方法spa
Request类把原来的request赋值给了self._request, 也就是说之后_request是咱们老的request,新的request是咱们这个Request类~~
即对request的功能进行的封装,扩展
继承APIView以后的数据在哪里来的
咱们用了rest_framework框架之后,咱们的request是从新封装的Request类~
request.query_params 存放的是咱们get请求的参数
request.data 存放的是咱们全部的数据,包括post请求的以及put,patch请求~~~
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,包括封装每一个方法的类,其实框架都帮咱们封装好了
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)
此次咱们只是让继承变的简单了一点而已,好像并无什么大的进步~~
内置源码提供的方法
actions这个默认参数其实就是咱们路由能够进行传参了~~~
下面这个循环~能够看出~咱们要传的参数是一个字段~key应该是咱们的请求方式,value应该对应咱们处理的方法~
这样咱们每一个视图就不用在写函数了~由于已经和内部实现的函数相对应了~
路由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 系统默认的~~
奉献一张图来看下咱们的继承顺序
路由传参写的特别多~~框架也帮咱们封装好了~
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