DRF 视图和路由
Django Rest Feamework 视图和路由
DRF的视图
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的一些区别~~当然还有~~后面我们还会说~~
我们写的视图可能对多个表进行增删改查,就导致我们的视图特别多重复的代码~~
那么我们尝试着来进行封装一下~~
第一次封装
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("删除的书籍不存在")
APIView视图
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

actions这个默认参数其实就是我们路由可以进行传参了~~~
下面这个循环~可以看出~我们要传的参数是一个字段~key应该是我们的请求方式,value应该对应我们处理的方法~
这样我们每个视图就不用在写函数了~因为已经和内部实现的函数相对应了~
第三次封装
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"})),
]
路由urls.py
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~~系统默认的~~
奉献一张图来看下我们的继承顺序~~~

DRF的路由
1,自定义路由
from django.conf.urls import url, include
from web.views import s11_render urlpatterns = [
url(r'^test/$', s11_render.TestView.as_view()),
url(r'^test\.(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view()),
url(r'^test/(?P<pk>[^/.]+)/$', s11_render.TestView.as_view()),
url(r'^test/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view())
]
urls.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .. import models class TestView(APIView):
def get(self, request, *args, **kwargs):
print(kwargs)
print(self.renderer_classes)
return Response('...')
views.py
2,半自动路由
from django.conf.urls import url, include
from web.views import s10_generic urlpatterns = [
url(r'^test/$', s10_generic.UserViewSet.as_view({'get': 'list', 'post': 'create'})),
url(r'^test/(?P<pk>\d+)/$', s10_generic.UserViewSet.as_view(
{'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]
urls.py
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from .. import models class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__" class UserViewSet(ModelViewSet):
queryset = models.UserInfo.objects.all()
serializer_class = UserSerializer
views.py
3,全自动路由
from django.conf.urls import url, include
from rest_framework import routers
from web.views import s10_generic router = routers.DefaultRouter()
router.register(r'users', s10_generic.UserViewSet) urlpatterns = [
url(r'^', include(router.urls)),
]
urls.py
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from .. import models class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__" class UserViewSet(ModelViewSet):
queryset = models.UserInfo.objects.all()
serializer_class = UserSerializer
views.py
DRF 视图和路由的更多相关文章
- DRF 视图组件,路由组件
视图组件 -- 第一次封装 -- GenericAPIView(APIView): queryset = None serializer_class = None def ge ...
- restfull规范、DRF视图和路由
一.restfull规范的简单介绍 1.介绍 REST:表述性状态转移,是一种web交互方案 资源:在web中只要有被引用的必要都是资源 URI: URI 统一资源标识符 URL 统一资源定位符 统一 ...
- DRF 的视图,路由和渲染器
DRF 的视图,路由和渲染器 1 视图 简单的增删改查 : ModelViewSet; 复杂的操作使用APIView 和 GenericViewSet APIView(View) class Home ...
- Django REST framework基础:视图和路由
DRF中的Request 在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等. 比如,区别于Dj ...
- Django Rest Framework 视图和路由
Django Rest Framework 视图和路由 DRF的视图 APIView 我们django中写CBV的时候继承的是View,rest_framework继承的是APIView,那么他们 ...
- 使用DRF视图集时自定义action方法
在我们用DRF视图集完成了查找全部部门,创建一个新的部门,查找一个部门,修改一个部门,删除一个部门的功能后,views.py的代码是这样子的: class DepartmentViewSet(Mode ...
- Rest_Framework的视图与路由
视图与路由 drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. Django ...
- 视图家族 & 路由组件
目录 视图家族 & 路由组件 视图集与路由组件 基于 GenericAPIView 的十大接口 基于 generics 包下工具视图类的六大基础接口 视图集 路由组件:必须配合视图集使用 自定 ...
- 068.Python框架Django之DRF视图集使用
一 视图集与路由的使用 使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中: list() 提供一组数据 retrieve() 提供单个数据 create() 创建数据 update() ...
随机推荐
- Windows10上使用Linux子系统(WSL)
Linux的Windows子系统让开发人员可以直接在Windows上运行Linux环境(包括大多数命令行工具,实用程序和应用程序),而无需建立在虚拟机的开销之上,整个系统共200多M,但包含了你能用到 ...
- Quartz-Spring定时任务器持久化,通过Service动态添加,删除,启动暂停任务
原文地址:https://blog.csdn.net/ljqwstc/article/details/78257091 首先添加maven的依赖: <!--quartz定时任务--> &l ...
- poj2104 主席树裸题
空间大小:n*lgn 复杂度:建树n*lgn 查询lgn #include <cstdio> #include <iostream> #include <algorit ...
- pycharm导入自己写的.py文件时,模块下方出现红色波浪线解决
点击菜单栏的File,选择Setting, 然后,选择需要导入的.py文件“所在的目录",而非项目根目录,右键 之后再导入该.py文件就不会出现红色波浪线了.
- 解决ERR Client sent AUTH, but no password is set
在搭建cookies池时,需要将账号密码保存到redis,保存时报错:ERR Client sent AUTH, but no password is set 报错原因:Redis服务器没有设置密码, ...
- use redis instance in docker hub
redis - Docker Hubhttps://hub.docker.com/_/redis
- MySQL数据库导入错误:ERROR 1064 (42000) 和 ERROR at line xx:
https://www.cnblogs.com/yeahgis/p/4358973.html mysql -hlocalhost -uroot -proot --default-character-s ...
- MariaDB 和 MySQL 比较
MariaDB.org - Supporting continuity and open collaborationhttps://mariadb.org/ MariaDB 和 MySQL 比较 - ...
- 文件搜索神器之everything
之前我提到了,在本地快速的进行文件的检索是平常工作中必要的部分,一个好的搜索软件会大大的提升我们的工作效率.就是它,everything,官方的网站地址是http://www.voidtools.co ...
- idea远程调试tomcat
在开发Spring Boot应用的时候,会发现有的时候在idea工具中运行程序和打包程序后在tomcat下运行程序的结果会不太一样,因此就需要远程调试tomcat. 首先在tomcat目录下的bin目 ...