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.模板渲染) -> ...
随机推荐
- 分享知识-快乐自己:IDEA下maven编译打包Java项目成jar包但是resource下配置文件无法编译
今天在写分布式项目的时候,一直无法编译 resource 下的配置文件:(在target文件夹下的 classes文件查看是否编译) 最后只能通过在POM文件中配置resources配置 得以解决: ...
- OpenCV——高斯模糊与毛玻璃特效
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...
- BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换
BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换 Description 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置 ...
- 洛谷 P2962 [USACO09NOV]灯Lights
题目描述 Bessie and the cows were playing games in the barn, but the power was reset and the lights were ...
- poj1094Sorting It All Out——拓扑排序
题目:http://poj.org/problem?id=1094 看到此题,首先觉得这是一种层层递进的关系,所以可以想到用拓扑排序: 就像人工排序,每次需要找到一个最小的,再找到新的最小的……所以用 ...
- DTP模型之一:(XA协议之三)MySQL数据库分布式事务XA优缺点与改进方案
1 MySQL 外部XA分析 1.1 作用分析 MySQL数据库外部XA可以用在分布式数据库代理层,实现对MySQL数据库的分布式事务支持,例如开源的代理工具:ameoba[4],网易的DDB,淘宝的 ...
- Spring管理Filter和Servlet(在servlet中注入spring容器中的bean)
在使用spring容器的web应用中,业务对象间的依赖关系都可以用context.xml文件来配置,并且由spring容器来负责依赖对象 的创建.如果要在servlet中使用spring容器管理业务对 ...
- <正则吃饺子> :关于 Matcher 的 replaceAll 的简单使用
在线文档地址:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh replaceAll public String replaceAll(String ...
- 【245】◀▶IEW-Unit10
Unit 10 Censorship 1. Model1题目及范文分析 Some parents believe that there is no harm in allowing their chi ...
- Windows下caffe安装详解(仅CPU)
本文大多转载自 http://blog.csdn.net/guoyk1990/article/details/52909864,加入部分自己实战心得. 1.环境:windows 7\VS2013 2. ...