drf4 视图与路由组件
APIView和View的区别
不管是View还是APIView最开始调用的都是as_view()
APIView继承了View, 并且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。

在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类

我们用了rest_framework框架以后,我们的request是重新封装的Request类
request.query_params 存放的是我们get请求的参数
request.data 存放的是我们所有的数据,包括post请求的以及put,patch请求
相比原来的django的request,我们现在的request更加精简,清晰了
现在我们知道了APIView和View的一些区别
视图的第一次封装
GenericAPIView 是对 APIView 的封装
xxxMixin 是对处理的各种请求方法的封装
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视图
APIView
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from .serializers import BookSerializer class GenericAPIView(APIView):
query_set = None
serializer_class = None def get_queryset(self):
return self.query_set def get_serializer(self, *args, **kwargs):
return self.serializer_class(*args, **kwargs) class ListModelMixin(object):
def list(self, request):
queryset = self.get_queryset()
ret = self.get_serializer(queryset, many=True)
return Response(ret.data) class CreateModelMixin(object):
def create(self, request):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors) class RetrieveModelMixin(object):
def retrieve(self, request, id):
book_obj = self.get_queryset().filter(id=id).first()
ret = self.get_serializer(book_obj)
return Response(ret.data) class UpdateModelMixin(object):
def update(self, request, id):
book_obj = self.get_queryset().filter(id=id).first()
serializer = self.get_serializer(book_obj, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors) class DestroyModelMixin(object):
def destroy(self, request, id):
book_obj = self.get_queryset().filter(id=id).first()
book_obj.delete()
return Response("") class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
pass class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
pass # class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
class BookView(ListCreateAPIView):
query_set = Book.objects.all() # 操作的表的对象
serializer_class = BookSerializer # 序列化的类 def get(self, request):
# book_obj = Book.objects.first()
# ret = BookSerializer(book_obj)
# book_list = Book.objects.all()
# book_list = self.get_queryset()
# ret = self.get_serializer(book_list, many=True)
# return Response(ret.data)
return self.list(request) def post(self, request):
# print(request.data)
# serializer = BookSerializer(data=request.data)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data)
# else:
# return Response(serializer.errors)
return self.create(request) # class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
class BookEditView(RetrieveUpdateDestroyAPIView):
query_set = Book.objects.all()
serializer_class = BookSerializer def get(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# ret = BookSerializer(book_obj)
# return Response(ret.data)
return self.retrieve(request, id) def put(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# serializer = BookSerializer(book_obj, data=request.data, partial=True)
# if serializer.is_valid():
# serializer.save()
# return Response(serializer.data)
# else:
# return Response(serializer.errors)
return self.update(request, id) def delete(self, request, id):
# book_obj = Book.objects.filter(id=id).first()
# book_obj.delete()
# return Response("")
return self.destroy(request, id)
视图的第一次封装
视图的第二次封装
class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
pass class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
pass class BookView(ListCreateAPIView):
pass class BookEditView(RetrieveUpdateDestroyAPIView):
pass
# 上面我们写的继承类太长了~~我们再改改 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应该对应我们处理的方法
这样我们每个视图就不用在写函数了,因为已经和内部实现的函数相对应了

因为是按照请求的方式不同反回的结果,所有第二次有两个视图函数
现在指定一个视图函数
# 视图类传参,不同的请求对应不同的方法
path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
注意一点,用框架封装的视图,我们url上的那个关键字参数要用pk,系统默认的
# class ViewSetMixin(object):
# def as_view(self):
# """
# 按照我们参数指定的去匹配 对应的方法
# get-->list
# :return: 不用我们去写,框架有
# """
ViewSetMixin 请求分发方法的原理,将不同的请求设置为不同的方法
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 第三次封装
第三次封装
from rest_framework.viewsets import ViewSetMixin class ModelViewSet(ViewSetMixin, GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
pass # from rest_framework.viewsets import ModelViewSet
# 框架内部已经实现了的,可以直接导入
#
class BookModelViewSet(ModelViewSet):
query_set = Book.objects.all() 自己封装的query_set
# queryset = Book.objects.all() # 框架的是queryset
serializer_class = BookSerializer
from rest_framework import views # APIView
from rest_framework import generics # GenericAPIView, 组合类
from rest_framework import mixins #混合继承类
from rest_framework import viewsets # ViewSetMixin 分发请求的类
我们现在的视图就只要写两行就可以了

用框架的时
路由为
path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
前面自己定义的是id,用框架时注意修改过来
path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
# 视图类传参.只有业务需求匹配性很强才用。通常情况下不这么用容易暴露接口
# path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
# path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
继承顺序

DRF的路由
from django.urls import path, include
from .views import BookView, BookEditView, BookModelViewSet
from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register(r"", BookModelViewSet) # 不能 加$ r"$" urlpatterns = [
# path('list', BookView.as_view()),
# path('retrieve/<int:id>', BookEditView.as_view()), # 视图类传参.只有业务需求匹配性很强才用。通常情况下不这么用容易暴露接口
# path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
# path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), ] urlpatterns += router.urls DefaultRouter
DRF的路由
通过框架我们可以把路由视图都变的非常简单,但是需要自定制的时候还是需要我们自己用APIView写
当不需要那么多路由的时候,也不要用这种路由注册
总之,一切按照业务需要去用
drf4 视图与路由组件的更多相关文章
- 视图家族 & 路由组件
目录 视图家族 & 路由组件 视图集与路由组件 基于 GenericAPIView 的十大接口 基于 generics 包下工具视图类的六大基础接口 视图集 路由组件:必须配合视图集使用 自定 ...
- VueJs(11)---vue-router(命名路由,命名视图,重定向别名,路由组件传参)
vue-router 上篇文章讲了第一篇vue-router相关文章,文章地址:VueJs(10)---vue-router(进阶1) 一.命名路由 有时候,通过一个名称来标识一个路由显得更方便一些, ...
- DRF 视图组件,路由组件
视图组件 -- 第一次封装 -- GenericAPIView(APIView): queryset = None serializer_class = None def ge ...
- drf二次封装response-APIViews视图家族-视图工具集-工具视图-路由组件
视图类传递参数给序列化类 (1).在视图类中实例化 序列化对象时,可以设置context内容. (2).在序列化类中的局部钩子.全局钩子.create.update方法中,都可以用self.conte ...
- vue路由组件传参
在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性. 使用 props 将组件和路由解耦: 取代与 $route 的耦合 const ...
- DRF 的视图,路由和渲染器
DRF 的视图,路由和渲染器 1 视图 简单的增删改查 : ModelViewSet; 复杂的操作使用APIView 和 GenericViewSet APIView(View) class Home ...
- 【DRF框架】路由组件
视图组件涉及的路由补充: from rest_framework.viewsets import ViewSetMixin 对路由进行了重新的分发,重写了as_view() 方法,重新封装了请求方法 ...
- 路由组件传参-props解耦方式(主要)
在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性. 使用 props 将组件和路由解耦: 取代与 $route 的耦合 const ...
- Vue路由组件vue-router
一.路由介绍 Creating a Single-page Application with Vue + Vue Router is dead simple. With Vue.js, we are ...
随机推荐
- java 错误
ERROR: JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = -2 解决在程序最后加一条语句system. ...
- Spring AOP初级——入门及简单应用
在上一篇<关于日志打印的几点建议以及非最佳实践>的末尾提到了日志打印更为高级的一种方式——利用Spring AOP.在打印日志时,通常都会在业务逻辑代码中插入日志打印的语句,这实际上是 ...
- Android倒计时实现
Android为我们封装好了一个抽象类CountDownTimer,可以实现计时器功能: /** * 倒数计时器 */ private CountDownTimer timer = new Count ...
- spring mvc 自动生成代码
generator mybaits 详细配置: 目录结构 执行命令 OK git:https://gitee.com/xxoo0_297/generator.git
- ARCore中根据屏幕坐标计算射线的算法
ARCore中提供了根据屏幕坐标.视口大小及view. project矩阵计算从屏幕坐标发射一条射线的方法,此方法用于3D拾取. class Ray { public final Vector3f o ...
- leetcode33
class Solution { public: int search(vector<int>& nums, int target) { //这个题是给一个排序数组,但是数组里面内 ...
- 多进程模块 multiprocessing
由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程. multiprocessing包是Python中的多进程 ...
- python中类与对象之继承
面对对象的三大特性之继承 1.什么是继承? 在程序中,继承指的是class与class之间的关系 继承是一种关系,必须存在两个class才能产生这种关系:被继承的class称为父类,继承的class称 ...
- 打开控制台F12弹出弹窗
window.onload=function(){ document.onkeydown=function(){ var e=w ...
- Codeforces Round #436 A. Fair Game
题意:给你n张卡片,上面写有数字,两个人选择两个数字,把相同数字的卡片都拿走,问能不能拿走所有的卡片并且两个人拿的卡片书相同. Examples Input 411272711 Output YES1 ...