博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
drf4 视图与路由组件
阅读量:5840 次
发布时间:2019-06-18

本文共 9921 字,大约阅读时间需要 33 分钟。

APIView和View的区别

不管是View还是APIView最开始调用的都是as_view()

APIView继承了View, 并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。

 

在View中的as_view方法返回了view函数,而view函数执行了self.dispatch()方法,但是这里的dispatch方法应该是我们APIView中的

 

去initialize_request中看下把什么赋值给了request,并且赋值给了self.request, 也就是我们在视图中用的request.xxx到底是什么~~

 

看到,这个方法返回的是Request这个类的实例对象~~我们注意我们看下这个Request类中的第一个参数request,是我们走我们django的时候的原来的request

 

我们看到了,这个Request类把原来的request赋值给了self._request, 也就是说以后_request是我们老的request,新的request是我们这个Request类

 

我们用了rest_framework框架以后,我们的request是重新封装的Request类

request.query_params 存放的是我们get请求的参数

request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求

相比原来的django的request,我们现在的request更加精简,清晰了

现在我们知道了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 APIViewfrom rest_framework.viewsets import GenericViewSetfrom rest_framework.response import Responsefrom .serializers import BookSerializerclass 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):    passclass 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):    passclass RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):    passclass BookView(ListCreateAPIView):    passclass BookEditView(RetrieveUpdateDestroyAPIView):    pass
# 上面我们写的继承类太长了~~我们再改改class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):    passclass RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):    passclass 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/
', 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):    passclass BookView(ModelViewSet):    queryset = Book.objects.all()    serializer_class = BookSerializer第三次封装
第三次封装
from rest_framework.viewsets import ViewSetMixinclass 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/
', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

 

前面自己定义的是id,用框架时注意修改过来

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

 

# 视图类传参.只有业务需求匹配性很强才用。通常情况下不这么用容易暴露接口 # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})), # path('retrieve/
', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

继承顺序

 

DRF的路由

 

from django.urls import path, includefrom .views import BookView, BookEditView, BookModelViewSetfrom rest_framework.routers import DefaultRouterrouter = DefaultRouter()router.register(r"", BookModelViewSet)  # 不能 加$ r"$"urlpatterns = [    # path('list', BookView.as_view()),    # path('retrieve/
', BookEditView.as_view()), # 视图类传参.只有业务需求匹配性很强才用。通常情况下不这么用容易暴露接口 # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})), # path('retrieve/
', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),]urlpatterns += router.urlsDefaultRouter
DRF的路由

通过框架我们可以把路由视图都变的非常简单,但是需要自定制的时候还是需要我们自己用APIView写

当不需要那么多路由的时候,也不要用这种路由注册

总之,一切按照业务需要去用

转载于:https://www.cnblogs.com/wenyule/p/10434256.html

你可能感兴趣的文章
argparse - 命令行选项与参数解析(转)
查看>>
修改上一篇文章的node.js代码,支持默认页及支持中文
查看>>
java只能的round,ceil,floor方法的使用
查看>>
将txt文件转化为json进行操作
查看>>
我的2014-相对奢侈的生活
查看>>
Java设计模式
查看>>
华为OJ 名字美丽度
查看>>
mysql-This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME 错误解决
查看>>
基本概念复习
查看>>
红黑树
查看>>
【数据库】
查看>>
WindowManager.LayoutParams 详解
查看>>
安卓中数据库的搭建与使用
查看>>
AT3908 Two Integers
查看>>
.NET 设计规范--.NET约定、惯用法与模式-2.框架设计基础
查看>>
sql 内联,左联,右联,全联
查看>>
C++关于字符串的处理
查看>>
Breaking parallel loops in .NET C# using the Stop method z
查看>>
[轉]redis;mongodb;memcache三者的性能比較
查看>>
让你的WPF程序在Win7下呈现Win8风格主题
查看>>