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 curl_setopt函数
(PHP 4 >= 4.0.2, PHP 5) curl_setopt — 设置一个cURL传输选项. 说明 bool curl_setopt ( resource $ch , int $opt ...
- PHP timezone_name_get() 函数
------------恢复内容开始------------ 实例 返回时区的名称: <?php$tz=timezone_open("Europe/Paris");echo ...
- PHP decbin() 函数
实例 把十进制转换为二进制: <?phpecho decbin("3") . "<br>";echo decbin("1" ...
- 5.21 省选模拟赛 luogu P4207 [NOI2005]月下柠檬树 解析几何 自适应辛普森积分法
LINK:月下柠檬树 之前感觉这道题很鬼畜 实际上 也就想到辛普森积分后就很好做了. 辛普森积分法的式子不再赘述 网上多的是.值得一提的是 这道题利用辛普森积分法的话就是一个解析几何的问题 而并非计算 ...
- C#与网络相关的两个监听的事件
今天遇到一个问题,当网络连接有问题的时候设计软件向用户发送通知,查了资料发现了两个相关的事件分享一下. 一.System.Net.NetworkInformation命名空间下的NetworkChan ...
- 删除数据-大表根据rowid来删除部分数据
偶遇需求,大表中需要删除部分数据.分批删除. declare TYPE type_table_rowid IS TABLE OF ROWID INDEX BY BINARY_INTEGER;table ...
- Python 写一个俄罗斯方块游戏
使用 Python 的 PyGame 库写一个俄罗斯方块游戏的逐步指南 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人 ...
- 方法解析之Method与ConstMethod介绍
HotSpot通过Method与ConstMethod来保存方法元信息. 1.Method Method没有子类,定义在method.hpp文件中,其类继承关系如下图: Method用于表示一个Jav ...
- JavaScript async/await 基础知识
async 作用: async函数返回一个 Promise对象,无论内部有没有await关键字. await 作用: await等待的是一个表达式,这个表达式的计算结果是 Promise 对象 或者是 ...
- Memcached高可用组件之repcached
在前边的tomcat session server msm的那篇博客我们用memcached做tomcat session服务器,默认官方memcached是不支持主从同步的,为了解决memcache ...