drf中View和router的详解
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的详解的更多相关文章
- 【Unity编程】Unity中关于四元数的API详解
本文为博主原创文章,欢迎转载,请保留出处:http://blog.csdn.net/andrewfan Unity中关于四元数的API详解 Quaternion类 Quaternion(四元数)用于计 ...
- [ 转载 ] Java开发中的23种设计模式详解(转)
Java开发中的23种设计模式详解(转) 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...
- Linux中/proc目录下文件详解
转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...
- JQuery在循环中绑定事件的问题详解
JQuery在循环中绑定事件的问题详解 有个页面上需要N个DOM,每个DOM里面的元素ID都要以数字结尾,比如说 ? 1 2 3 <input type="text" nam ...
- C#中的Linq to Xml详解
这篇文章主要介绍了C#中的Linq to Xml详解,本文给出转换步骤以及大量实例,讲解了生成xml.查询并修改xml.监听xml事件.处理xml流等内容,需要的朋友可以参考下 一.生成Xml 为了能 ...
- 批处理中的echo命令图文详解
批处理中的echo命令图文详解 1. Echo 显示当前ECHO的状态:ECHO ON 或者ECHO OFF 2. ECHO ON 将ECHO状态设置为ON,将显示命令行,也就是前面的C:\>类 ...
- C#中的预处理器指令详解
这篇文章主要介绍了C#中的预处理器指令详解,本文讲解了#define 和 #undef.#if.#elif.#else和#endif.#warning和#error.#region和#endregio ...
- SVN中tag branch trunk用法详解
SVN中tag branch trunk用法详解 2010-05-24 18:32 佚名 字号:T | T 本文向大家简单介绍一下SVN中tag branch trunk用法,SVN中tag bran ...
- JavaScript中的鼠标滚轮事件详解
JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...
随机推荐
- PHP fileperms() 函数
定义和用法 fileperms() 函数返回文件或目录的权限. 如果成功,该函数以数字形式返回权限.如果失败,则返回 FALSE. 语法 fileperms(filename) 参数 描述 filen ...
- PHP lstat() 函数
定义和用法 lstat() 函数返回关于文件或符号连接的信息. 该函数将返回一个包含下列元素的数组: [0] 或 [dev] - 设备编号 [1] 或 [ino] - inode 编号 [2] 或 [ ...
- org.hibernate.AssertionFailure: null id 错误
对象属性有Blob类型: 而Blob需在输入流中读取: InputStream in = new FileInputStream(url.getFile()); Blob bookPic = lobH ...
- 使用Flask开发简单接口(2)--POST请求接口
今天我们继续学习如何使用Flask开发POST接口:用户注册接口和用户登录接口. request接收参数 当我们在页面发出一个POST请求,请求传到服务器时,需要如何拿到当前请求的数据呢?在Flask ...
- 从零写一个Asp.net core手脚架 (异常处理)
既然是手脚架,那么肯定得明白,手脚架是有限资源的一个整合,我们尽可能完善它,并保留可扩展性才是最终目的,尽可能减少硬编码,让业务不满足的情况下,可以自行修改 我们把解决方案取名Asp.netCoreT ...
- windows下Nginx+RTMP部署
在windows下部署参考博客:https://blog.csdn.net/l1028386804/article/details/80022437 参考这个部署完成后,一般没有什么问题,可以看到视频 ...
- SpringMvc接收multipart/form-data 传输的数据 及 PostMan各类数据类型的区别
前段时间遇到一个问题,在spring mvc 服务端接收post请求时,通过html 表单提交的时候,服务端能够接收到参数的值.但是使用httpclient4.3构造post请求,却无法接收到参数的值 ...
- CSS页面布局与网格(上)
1.布局规划 1.1 网格 网格系统是设计师在切分布局时作为参照的一组行和列. 1.2 布局辅助类 类名用于为布局添加样式.为了让样式可以重用,让类名表达其意图. .column { /* 一般列的样 ...
- 2020重新出发,JAVA学前了解,Windosws常用快捷键
前言:windows 常用快捷键 标准计算机键盘共104键,除了26个字母键.符号键.数字键外,剩下的都是一些功能键: 键盘功能键 常用功能键:Esc.Tab.Caps Lock.Shift.Ctrl ...
- 【LeetCode/LintCode】 题解丨字节跳动试题:第k大的子数组
给定一个长度为n的数组a,它有n(n+1)/2个子数组.请计算这些子数组的和,然后按照升序排列,并返回排序后第k个数. 1≤n≤10^5 1≤ai≤10^9 1≤k≤n(n+1)/2 在线 ...