Django-Rest-Framework的视图和路由
Django-Rest-Framework的视图和路由
Django-Rest-Framework的视图
APIView
django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们两个有什么不同呢
urlpatterns = [
url(r'^book$', BookView.as_view()),
url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
]
可以看到,不管是View还是APIView最开始调用的都是as_view()方法,那走进源码看看

我们能看到,APIView继承了View, 并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。
那我们看看View中的as_view()方法做了什么

我们看到了~在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类
那我们继承APIView之后请求来的数据都在哪呢~~

我们用了rest_framework框架以后,我们的request是重新封装的Request类~
request.query_params 存放的是我们get请求的参数
request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求
相比原来的django的request,我们现在的request更加精简,清晰了~~~
现在我们知道了APIView和View的一些区别~~当然还有~~后面还会说~~
我们写的视图可能对多个表进行增删改查,就导致我们的视图特别多重复的代码~~
那么我们尝试着来进行封装一下~~
第一次封装
APIView视图
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("删除的书籍不存在")
第一次封装
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(object):
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
class CreateModelMixin(object):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.validated_data)
else:
return Response(serializer.errors)
class RetrieveModelMixin(object):
def retrieve(self, request, id, *args, **kwargs):
book_obj = self.get_queryset().filter(pk=id).first()
book_ser = self.get_serializer(book_obj)
return Response(book_ser.data)
class UpdateModelMixin(object):
def update(self, request, id, *args, **kwargs):
book_obj = self.get_queryset().filter(pk=id).first()
book_ser = self.get_serializer(book_obj, 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)
class DestroyModelMixin(object):
def destroy(self, request, id, *args, **kwargs):
queryset = self.get_queryset()
try:
queryset.get(pk=id).delete()
return Response("")
except Exception as e:
return Response("信息有误")
# 我们把公共的部分抽出来 这样不管写多少表的增删改查都变的很简单
# 这样封装后我们的视图会变成这样
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
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(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
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 destroy(self, request, id, *args, **kwargs):
return self.delete(request, id, *args, **kwargs)
我们封装的GenericAPIView,包括封装每个方法的类,其实框架都帮我们封装好了~~
我们可以直接继承这些类来实现上面的视图可是还有没有更简单的方法呢~我们再次封装一下~~
第二次封装
# 上面我们写的继承类太长了~~我们再改改
class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
pass
class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
pass
class 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

action这个默认参数其实就是我们路由可以进行传参了
下面这个循环~可以看出~我们要传的参数是一个字段~key应该是我们的请求方式,value应该对应我们处理的方法~
这样我们每个视图就不用在写函数了~因为已经和内部实现的函数相对应了~
第三次封装
路由 urls.py
urlpatterns = [
# url(r'^book$', BookView.as_view()),
# url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
url(r'^book/(?P<pk>\d+)$', BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
]
第三次封装
from rest_framework.viewsets import ViewSetMixin
# class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
# queryset = Book.objects.all()
# serializer_class = BookSerializer
# 如果我们再定义一个类
class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
pass
class BookView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
我们现在的视图就只要写两行就可以了
其实我们写的所有的视图~框架都帮我们封装好了
注意一点~用框架封装的视图~我们url上的那个关键字参数要用pk~系统默认的
奉献一张图来看下我们的继承顺序

Django-Rest-Framework的路由
我们上面的路由传参写的特别多~~框架也帮我们封装好了~
from .views import BookView
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r"book", BookView)
urlpatterns = [
# url(r'^book$', BookView.as_view()),
# url(r'^book/(?P<id>\d+)$', BookEditView.as_view()),
# url(r'^book$', BookView.as_view({"get": "list", "post": "create"})),
# url(r'^book/(?P<pk>\d+)$', BookView.as_view({"get": "retrieve", "patch": "update", "delete": "destroy"})),
]
urlpatterns += router.urls
我们可以看到通过框架我们可以把路由视图都变的非常简单~~
但是需要自定制的时候还是需要我们自己用APIView写,当不需要那么多路由的时候,也不要用这种路由注册~~
总之一切按照业务需要去用~~~
Django-Rest-Framework的视图和路由的更多相关文章
- Django Rest framework 之 视图
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- Django rest framework (视图类详解)
官网:https://www.django-rest-framework.org/api-guide/viewsets/ 在django rest framework 视图中一共有N个类 第一类:AP ...
- Django 的 一些基本操作:视图函数,路由配置
当安装好Django 通过上篇的随笔创好项目我们就能来耍下了, 但你会在你的项目中发现有一个settings.py 的文件,对的你肯定想到了需要配置,好了话不多说 Settings.py 找到下面的位 ...
- DRF Django REST framework 之 视图组件(四)
引言 在我们有几十上百的视图类,都有get,post等方法,在功能类似时,会导致大量的重复代码出现,显然还有很多可以优化的地方.这也就有了视图组件,它的功能非常强大,能很好的优化接口逻辑. 视图组件 ...
- Django rest framework(8)---- 视图和渲染器
django rest framework 之视图 序列化器 PagerSerialiser from rest_framework import serializers from api im ...
- Django Rest framework 之 序列化
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- Django Rest framework 之 版本
RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...
- Django Rest framework 之 权限
django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) django res ...
- Django Rest framework 之 认证
django rest framework 官网 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest fra ...
- django rest framework restful 规范
内容回顾: . django请求生命周期 -> 执行遵循wsgi协议的模块(socket服务端) -> 中间件(路由匹配) -> 视图函数(业务处理:ORM.模板渲染) -> ...
随机推荐
- Ruby 仿 C 结构体:CStruct 的一些例子
1. [代码]最简单的例子 # CStruct Examplesrequire 'cstruct' # example:# struct Point in C\C++ (32-b ...
- Ajax处理后台返回的Json数据
// 处理后台传来的Json字符串装换成Json对象 var dataJson = JSON.parse(data); // 此时可以从Json对象中取值 if(dataJson.result == ...
- SqL注入攻击实践
研究缓冲区溢出的原理,至少针对两种数据库进行差异化研究 缓冲区溢出原理 缓冲区溢出是指当计算机程序向缓冲区内填充的数据位数超过了缓冲区本身的容量.溢出的数据覆盖在合法数据上.理想情况是,程序检查数据长 ...
- 华为USG6500系列
华为USG6500: ssh 登录配置 time-range 相关配置:<USG6000V1>system-view Enter system view, return user view ...
- nginx 轮询模式 nginx_upstream_jvm_route 插件安装
使用nginx_upstream_jvm_route插件的目的是为了保证在轮询机制下的session的共享 前提:源码方式安装nginx.patch命令 1.下载nginx_upstream_jvm_ ...
- mysql错误-修改mysql.sock位置
在Mysql下有时候会出现mysql.sock位置错误,导致无法链接数据库. mac下报错的时候: 首先修改my.cnf 位置在/etc/my.cnf下,假如没有的话,去/usr/locate/mys ...
- TextBox的OnTextboxChanged事件里对Text重新赋值带中文, 导致崩溃
今天遇到一个超级bug, Textbox做了限制, 只能输入数字. 结果在搜狗输入法输入中文时导致崩溃, 出错信息如下: 未处理 System.InvalidOperationException ...
- angular.foreach 格式
angular有自己的生命周期.循环给一个 angular监听的变量复值时.最好还是用angular自带的循环方法.“angular.foreach” 格式: var objs =[{a:1},{a: ...
- query builder 在线生成sql
http://devtools.korzh.com/easyquery/javascript/docs/javascript-query-builder-php
- java——类的封装
public void setName(String str) { name=str; } public void setAge(int a) //set方法需要在括号中定义数据类型 { if(a&g ...