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数据类型

第一版封装

app/views

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, pk):
query_set = Book.objects.filter(pk=pk).first()
book_ser = BookSerializer(query_set)
return Response(book_ser.data) def patch(self, request, pk):
query_set = Book.objects.filter(pk=pk).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, pk):
query_set = Book.objects.filter(pk=pk).first()
if query_set:
query_set.delete()
return Response("")
else:
return Response("删除的书籍不存在")

使用Mixin封装方法

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: def list(self,request,*args,**kwargs):
queryset = self.get_queryset()
book_sel = self.get_serializer(queryset,many=True)
return Response(book_sel.data) class CreateModelMixin: def create(self,request,*args,**kwargs):
book_sel = self.serializer_class(data=request.data)
if book_sel.is_valid():
book_sel.save()
return Response(book_sel.data)
else:
return Response(book_sel.errors) class UpdateModelMixin: def update(self,request,pk,*args,**kwargs):
book_obj = self.get_queryset().filter(pk=pk).first()
book_sel = self.serializer_class(book_obj,data=request.data,partial=True)
if book_sel.is_valid():
book_sel.save()
return Response(book_sel.data)
else:
return Response(book_sel.errors) class RetrieveModelMixin: def retrieve(self,request,pk,*args,**kwargs):
book_obj = self.get_queryset().filter(pk=pk).first()
book_sel = self.serializer_class(book_obj)
return Response(book_sel.data) class DestroyModelMixin:
def destroy(self, request, pk, *args, **kwargs):
queryset = self.get_queryset()
try:
queryset.get(pk=pk).delete()
return Response("")
except Exception as e:
return Response("信息有误") # Create your views here.
class BookEditView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = models.Book.objects
serializer_class = BookSerializers
def get(self,request,pk,*args,**kwargs):
return self.retrieve(request,pk,*args,**kwargs) def patch(self,request,pk,*args,**kwargs):
return self.update(request,pk,*args,**kwargs) def delete(self,request,pk,*args,**kwargs):
return self.destroy(request,pk,*args,**kwargs) class BookView(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = models.Book.objects
serializer_class = BookSerializers
def get(self,request,*args,**kwargs):
return self.list(request,*args,**kwargs) def post(self,request,*args,**kwargs):
return self.create(request,*args,**kwargs) # 技术点:因为drf中的GenericAPIView提供了queryset和serializer_class,如果要继承GenericAPIView,
# 则必须重写这两个字段,且GenericAPIView提供get_queryset和get_serializer两个方法
# Mixin类不用继承其他API,只是单独提供方法接口,必须跟其他API类混合继承

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

第二版封装

# 上面我们写的继承类太长了~~我们再改改

class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
pass class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
pass class BookEditView(RetrieveUpdateDestroyAPIView):
queryset = models.Book.objects
serializer_class = BookSerializers
def get(self,request,pk,*args,**kwargs):
return self.retrieve(request,pk,*args,**kwargs) def patch(self,request,pk,*args,**kwargs):
return self.update(request,pk,*args,**kwargs) def delete(self,request,pk,*args,**kwargs):
return self.destroy(request,pk,*args,**kwargs) class BookView(ListCreateAPIView):
queryset = models.Book.objects
serializer_class = BookSerializers
def get(self,request,*args,**kwargs):
return self.list(request,*args,**kwargs) def post(self,request,*args,**kwargs):
return self.create(request,*args,**kwargs)

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

第三版封装

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

urlpatterns = [
url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
url(r'^retrieve/(?P<pk>\d+)$', BookEditView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})), //这里要注意的是,使用这种传参的view,传入的动态id要命名为pk
] urls.py
from rest_framework.viewsets import ViewSetMixin

# class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
# queryset = Book.objects.all()
# serializer_class = BookSerializer # 如果我们再定义一个类
class ModelViewSet(ViewSetMixin, ListCreateAPIView):
pass
class OwnViewSet(ViewSetMixin,RetrieveUpdateDestroyAPIView) class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer class BookEditView(OwnViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer

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

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

drf的路由

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

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r"book", BookView) urlpatterns = [ ]
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. 5.4 省选模拟赛 修改 线段树优化dp 线段树上二分

    LINK:修改 题面就不放了 大致说一下做法.不愧是dls出的题 以前没见过这种类型的 不过还是自己dp的时候写丑了. 从这道题中得到一个结论 dp方程要写的优美一点 不过写的过丑 优化都优化不了. ...

  2. IDEA查看项目日志Version Control、log

    打开IDEA找到以下两处:    右下角git    黄色指针指向当前项目的版本    选中初始化项目,点击右键选择"Checkout Revision 1db2f3d5",如下图 ...

  3. 【FZYZOJ】下片 题解(最短路+超级源点)

    题目描述 为了提高服务器的耐受能力,很多流量大的网站都会架设多台服务器,而互联网的路由能找到线路最短的一台服务器. 现在UOI想要下片,他有好多台电脑,又有好多服务器可以提供下载.UOI将给你一个网络 ...

  4. Access to XMLHttpRequest at xxxx from origin ‘null‘ has been blocked by CORS policy:

    使用前后端分离的方式创建web项目的时候出现问题: 这是因为 ajax 请求的对应的域在本地的一个文件路径,比如在D盘的某个文件夹,这里存放的都是前端文件: 但是对应的服务器是 localhost 的 ...

  5. MySQL--->高级对象

    本章目标: 掌握MySQL视图 掌握MySQL存储过程 掌握MySQL触发器 1.视图: 视图就是一条select语句执行后返回的结果集. 使用场景:权限控制的时候不希望用户访问表中某些敏感信息的列 ...

  6. java从零到变身爬虫大神

    刚开始先从最简单的爬虫逻辑入手 爬虫最简单的解析面真的是这样 import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import java. ...

  7. X86汇编——计算斐波那契数列程序(详细注释和流程图说明)

    X86汇编实现斐波那契数列 程序说明: 输入斐波那契数列的项数, 然后依次输出斐波那契数列, 输入的项数小于256且为数字, 计算的项数不能超过2^16次方, 输入失败是 不会回显数字 因为存结果是A ...

  8. Kubernetes基于haproxy实现ingress服务暴露

    HAproxy Ingress控制器 HAproxy Ingress简介 HAProxy Ingress watches in the k8s cluster and how it builds HA ...

  9. 使用nebula把联想个人云存储映射到当前网络使用的方法

    整个过程涉及三个主机一个是家里的台式机 home 内网ip为192.168.69.101一个是公司的笔记本 mac一个是有公网ip的服务器 server云存储在家里和home在同一个内网,IP地址为1 ...

  10. ThinkPHP 6.0 基础教程 - 安装

    ThinkPHP6.0 的环境: PHP >= 7.1.0 我本地环境: Win10 PhpStudy 安装 PhpStudy 如果你已经安装 PhpStudy 或其他环境,请忽略这里 安装方法 ...