Rest Framework 视图和路由

因为涉及到视图层面了,而且下面的例子会反复用到request.data,所以我决定带大家稍微看下源码,感兴趣的可以自己深入了解

无论是View还是APIView最开始都是调用as_view()

大致过了下APIView给我们封装的数据

总结一下

  • 旧的request封装到新request属性_request里
  • 继承APIView,重新封装的request.query_params相当于旧的request.GET
  • request.data相当于旧的request.POST和request.FILES,且支持json数据类型

第一版封装

  1. app/views
  2. class BookView(APIView):
  3. def get(self, request):
  4. query_set = Book.objects.all()
  5. book_ser = BookSerializer(query_set, many=True)
  6. return Response(book_ser.data)
  7. def post(self, request):
  8. query_set = request.data
  9. book_ser = BookSerializer(data=query_set)
  10. if book_ser.is_valid():
  11. book_ser.save()
  12. return Response(book_ser.validated_data)
  13. else:
  14. return Response(book_ser.errors)
  15. class BookEditView(APIView):
  16. def get(self, request, pk):
  17. query_set = Book.objects.filter(pk=pk).first()
  18. book_ser = BookSerializer(query_set)
  19. return Response(book_ser.data)
  20. def patch(self, request, pk):
  21. query_set = Book.objects.filter(pk=pk).first()
  22. book_ser = BookSerializer(query_set, data=request.data, partial=True)
  23. if book_ser.is_valid():
  24. book_ser.save()
  25. return Response(book_ser.validated_data)
  26. else:
  27. return Response(book_ser.errors)
  28. def delete(self, request, pk):
  29. query_set = Book.objects.filter(pk=pk).first()
  30. if query_set:
  31. query_set.delete()
  32. return Response("")
  33. else:
  34. return Response("删除的书籍不存在")

使用Mixin封装方法

  1. class GenericAPIView(APIView):
  2. queryset = None
  3. serializer_class = None
  4. def get_queryset(self):
  5. return self.queryset.all()
  6. def get_serializer(self,*args,**kwargs):
  7. return self.serializer_class(*args,**kwargs)
  8. class ListModelMixin:
  9. def list(self,request,*args,**kwargs):
  10. queryset = self.get_queryset()
  11. book_sel = self.get_serializer(queryset,many=True)
  12. return Response(book_sel.data)
  13. class CreateModelMixin:
  14. def create(self,request,*args,**kwargs):
  15. book_sel = self.serializer_class(data=request.data)
  16. if book_sel.is_valid():
  17. book_sel.save()
  18. return Response(book_sel.data)
  19. else:
  20. return Response(book_sel.errors)
  21. class UpdateModelMixin:
  22. def update(self,request,pk,*args,**kwargs):
  23. book_obj = self.get_queryset().filter(pk=pk).first()
  24. book_sel = self.serializer_class(book_obj,data=request.data,partial=True)
  25. if book_sel.is_valid():
  26. book_sel.save()
  27. return Response(book_sel.data)
  28. else:
  29. return Response(book_sel.errors)
  30. class RetrieveModelMixin:
  31. def retrieve(self,request,pk,*args,**kwargs):
  32. book_obj = self.get_queryset().filter(pk=pk).first()
  33. book_sel = self.serializer_class(book_obj)
  34. return Response(book_sel.data)
  35. class DestroyModelMixin:
  36. def destroy(self, request, pk, *args, **kwargs):
  37. queryset = self.get_queryset()
  38. try:
  39. queryset.get(pk=pk).delete()
  40. return Response("")
  41. except Exception as e:
  42. return Response("信息有误")
  43. # Create your views here.
  44. class BookEditView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
  45. queryset = models.Book.objects
  46. serializer_class = BookSerializers
  47. def get(self,request,pk,*args,**kwargs):
  48. return self.retrieve(request,pk,*args,**kwargs)
  49. def patch(self,request,pk,*args,**kwargs):
  50. return self.update(request,pk,*args,**kwargs)
  51. def delete(self,request,pk,*args,**kwargs):
  52. return self.destroy(request,pk,*args,**kwargs)
  53. class BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
  54. queryset = models.Book.objects
  55. serializer_class = BookSerializers
  56. def get(self,request,*args,**kwargs):
  57. return self.list(request,*args,**kwargs)
  58. def post(self,request,*args,**kwargs):
  59. return self.create(request,*args,**kwargs)
  60. # 技术点:因为drf中的GenericAPIView提供了queryset和serializer_class,如果要继承GenericAPIView,
  61. # 则必须重写这两个字段,且GenericAPIView提供get_queryset和get_serializer两个方法
  62. # Mixin类不用继承其他API,只是单独提供方法接口,必须跟其他API类混合继承

感觉经过这么一封装,每个类中的方法看起来清爽多了,我们还可以继续封装

第二版封装

  1. # 上面我们写的继承类太长了~~我们再改改
  2. class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
  3. pass
  4. class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
  5. pass
  6. class BookEditView(RetrieveUpdateDestroyAPIView):
  7. queryset = models.Book.objects
  8. serializer_class = BookSerializers
  9. def get(self,request,pk,*args,**kwargs):
  10. return self.retrieve(request,pk,*args,**kwargs)
  11. def patch(self,request,pk,*args,**kwargs):
  12. return self.update(request,pk,*args,**kwargs)
  13. def delete(self,request,pk,*args,**kwargs):
  14. return self.destroy(request,pk,*args,**kwargs)
  15. class BookView(ListCreateAPIView):
  16. queryset = models.Book.objects
  17. serializer_class = BookSerializers
  18. def get(self,request,*args,**kwargs):
  19. return self.list(request,*args,**kwargs)
  20. def post(self,request,*args,**kwargs):
  21. return self.create(request,*args,**kwargs)

感觉只是把类中的继承稍微简化了下,并不是特别的优雅,来康康第三版

第三版封装

我们知道,一般的View执行as_view()不能传入参数,接下来要介绍的ViewSetMixin,重写了as_view(actions),可以传入我们需要的参数

  1. urlpatterns = [
  2. url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
  3. url(r'^retrieve/(?P<pk>\d+)$', BookEditView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})), //这里要注意的是,使用这种传参的view,传入的动态id要命名为pk
  4. ]
  5. urls.py
  1. from rest_framework.viewsets import ViewSetMixin
  2. # class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
  3. # queryset = Book.objects.all()
  4. # serializer_class = BookSerializer
  5. # 如果我们再定义一个类
  6. class ModelViewSet(ViewSetMixin, ListCreateAPIView):
  7. pass
  8. class OwnViewSet(ViewSetMixin,RetrieveUpdateDestroyAPIView)
  9. class BookView(ModelViewSet):
  10. queryset = Book.objects.all()
  11. serializer_class = BookSerializer
  12. class BookEditView(OwnViewSet):
  13. queryset = Book.objects.all()
  14. serializer_class = BookSerializer

我们现在的视图就只要写两行就可以了,其实我们写的所有的视图~框架都帮我们封装好了,刚刚上面用的例子都是手动封装

奉献一张图来看下我们的继承顺序~~~

drf的路由

我们上面的路由传参写的特别多~~框架也帮我们封装好了~

  1. from rest_framework.routers import DefaultRouter
  2. router = DefaultRouter()
  3. router.register(r"book", BookView)
  4. urlpatterns = [
  5. ]
  6. urlpatterns += router.urls

通过框架的路由可以看出,手写的代码几乎没有了,这里提出一点建议,如果自己的业务逻辑不是跟增删改查特别耦合

不建议用drf提供的路由组件,因为这样会暴露很多的接口,不太安全,总之,一般我们很少用到这个组件,还是尽量自己手写

总结

类的继承链越高,所拥有的功能也就越少,可定制化的程度就越高,尽管上面我们用底层的类,特别轻松的实现了功能,

但需要自定制时,还是继承APIView实现自己的业务逻辑,总之一切按照业务逻辑来走

参考链接

https://www.cnblogs.com/GGGG-XXXX/articles/9675911.html

drf中View和router的详解的更多相关文章

  1. 【Unity编程】Unity中关于四元数的API详解

    本文为博主原创文章,欢迎转载,请保留出处:http://blog.csdn.net/andrewfan Unity中关于四元数的API详解 Quaternion类 Quaternion(四元数)用于计 ...

  2. [ 转载 ] Java开发中的23种设计模式详解(转)

    Java开发中的23种设计模式详解(转)   设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...

  3. Linux中/proc目录下文件详解

    转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...

  4. JQuery在循环中绑定事件的问题详解

    JQuery在循环中绑定事件的问题详解 有个页面上需要N个DOM,每个DOM里面的元素ID都要以数字结尾,比如说 ? 1 2 3 <input type="text" nam ...

  5. C#中的Linq to Xml详解

    这篇文章主要介绍了C#中的Linq to Xml详解,本文给出转换步骤以及大量实例,讲解了生成xml.查询并修改xml.监听xml事件.处理xml流等内容,需要的朋友可以参考下 一.生成Xml 为了能 ...

  6. 批处理中的echo命令图文详解

    批处理中的echo命令图文详解 1. Echo 显示当前ECHO的状态:ECHO ON 或者ECHO OFF 2. ECHO ON 将ECHO状态设置为ON,将显示命令行,也就是前面的C:\>类 ...

  7. C#中的预处理器指令详解

    这篇文章主要介绍了C#中的预处理器指令详解,本文讲解了#define 和 #undef.#if.#elif.#else和#endif.#warning和#error.#region和#endregio ...

  8. SVN中tag branch trunk用法详解

    SVN中tag branch trunk用法详解 2010-05-24 18:32 佚名 字号:T | T 本文向大家简单介绍一下SVN中tag branch trunk用法,SVN中tag bran ...

  9. JavaScript中的鼠标滚轮事件详解

    JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...

随机推荐

  1. PHP strpbrk() 函数

    实例 在字符串中搜索字符 "oe",并返回字符串中从指定字符第一次出现的位置开始的剩余部分: <?php高佣联盟 www.cgewang.comecho strpbrk(&q ...

  2. 从入门到熟悉HTTPS的9个问题

    原文:bestswifter   https://juejin.im/post/58c5268a61ff4b005d99652a Q1: 什么是 HTTPS? BS: HTTPS 是安全的 HTTP ...

  3. ios迅雷上架成功的秘密 背后的“苹果TF签名”

    距离ios迅雷从App Store下架已经过去很久了,小微经常看到知乎里有很多迅雷用户到处寻找可以下载应用的渠道.近期迅雷被爆“好消息”iOS 迅雷(官方版)正式上架 App Store,此消息一出可 ...

  4. webMvcConfigurer的详情

                  摘要 Spring的WebMvcConfigurer接口提供了很多方法让我们来定制SpringMVC的配置.而且Spring还提供了WebMvcConfigurerAdap ...

  5. 史上最简单操作!!!!!!!Window Server2012 修改远程桌面端口号

    Window Server2012 修改远程桌面端口号   Win + R 输入 regedit 打开注册表编辑器 在注册表编辑器中找到 PortNumber 双击 PortNumber,选择10进制 ...

  6. java_方法的定义、调用、重载

    方法的定义 1 概述 方法:就是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能. 当我们需要这个功能的时候,就可以去调用.这样即实现了代码的复用性,也解决了代码冗余的现象. 2 ...

  7. java 判断集合元素唯一的原理

    一 ArrayList的contains方法判断元素是否重复原理 ArrayList的contains方法会使用调用方法时,传入的元素的equals方法依次与集合中的旧元素 所比较,从而根据返回的布尔 ...

  8. 2020-04-09:TCP的四次挥手中为什么要有TIME_WAIT状态?

    TIME_WAIT状态存在有两个原因.<1>可靠终止TCP连接.如果最后一个ACK报文因为网络原因被丢弃,此时server因为没有收到ACK而超时重传FIN报文,处于TIME_WAIT状态 ...

  9. C#LeetCode刷题之#551-学生出勤纪录 I​​​​​​​(Student Attendance Record I)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3953 访问. 给定一个字符串来代表一个学生的出勤纪录,这个纪录仅 ...

  10. DeepLab系列

    论文: (DeepLabV1)Semantic image segmentation with deep convolutional nets and fully connected CRFs (De ...