def --- DRF视图的详细用法

视图的用法

1.DRF中的request以及response

DRF中传入视图的request对象 不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。

DRF中传入视图的response对象 REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

添加配置文件


  1. REST_FRAMEWORK = {
  2. ‘DEFAULT_RENDERER_CLASSES‘: ( # 默认响应渲染类
  3. ‘rest_framework.renderers.JSONRenderer‘, # json渲染器
  4. ‘rest_framework.renderers.BrowsableAPIRenderer‘, # 浏览API渲染器
  5. )
  6. }

2.DRF中的视图的优势

首先我们来看不使用DRF,视图怎么实现

通用视图基类与扩展类,以简化视图的编写


  1. # 处理admin站点的请求
  2. class BooksAPIView(View):
  3. # GET /books/
  4. def get(self, request):
  5. books = BookInfo.objects.all()
  6. book_list = []
  7. for book in books:
  8. book_list.append({
  9. ‘id‘: book.id,
  10. ‘btitle‘: book.btitle,
  11. ‘bread‘: book.bread,
  12. ‘bcomment‘: book.bcomment,
  13. ‘is_delete‘: book.is_delete,
  14. # 注意此处要加上url才能访问到图片的地址
  15. ‘image‘: book.image.url if book.image else ‘‘,
  16. ‘bpub_date‘: book.bpub_date
  17. })
  18. return JsonResponse(book_list, safe=False)

代码块1

怎么样,是不是感觉很复杂。我们的DRF就可以帮我们处理其中的大部分代码而不用我们自己去处理!!!

重点来了,怎么实现呢?

首先我们得了解一下,当我们不去自己继承View类定义类视图时,DRF给哦们提供了几个继承自View类的丰富的类

1.基类:APIView

APIView是REST framework提供的所有视图的基类,继承自Django的View父类。

APIViewView的不同之处在于:

  • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
  • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
  • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
  • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制

支持定义的属性:

  • authentication_classes 列表或元祖,身份认证类
  • permissoin_classes 列表或元祖,权限检查类
  • throttle_classes 列表或元祖,流量控制类

APIView中仍和普通的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。


  1. class BookListView(APIView):
  2. """使用APIView实现“获取所有图书信息”接口"""
  3. def get(self, request):
  4. """
  5. 获取所有图书信息
  6. GET /books/
  7. :param request: Request类型的对象
  8. :return: JSON
  9. """
  10. qs = BookInfo.objects.all() # 查询要序列化的模型数据
  11. serializer = BookInfoSerializer(qs, many=True) # 准备序列化器:将模型数据转字典数据
  12. return Response(serializer.data) # 响应序列化的结果

代码块2

对比代码块1,发现确实工作量减少很多

2.基类:GenericAPIView

提供的关于序列化器使用的属性与方法

具体实现例子:


  1. class BookListView(GenericAPIView):
  2. """使用GenericAPIView实现“获取所有图书信息”接口"""
  3. serializer_class = BookInfoSerializer # 指定序列化器
  4. queryset = BookInfo.objects.all() # 指定查询集
  5. def get(self, reqeust):
  6. """
  7. 获取所有图书信息
  8. GET /books/
  9. :param reqeust: Request类型的对象
  10. :return: JSON
  11. """
  12. qs = self.get_queryset() # 获取查询集
  13. serializer = self.get_serializer(qs, many=True)# 创建序列化器对象
  14. return Response(serializer.data) # 响应序列化后的数据

我们发现这样做反而增加了两行代码,怎么说他优化了呢?别急,下边的GenericAPIView扩展类要大显身手了

3.配合GenericAPIView使用的几个扩展类

我们发现前边的两个父类还需要进行函数的定义去处理不同的请求,这样我们还得在函数里边实现查询集以及序列化器的指定,工作量仍然很大。怎么解决呢?

GenericAPIView的五个扩展类给我们提供了五个方法分别进行增删改查的不同操作,这样我们就不用写那么多函数啦!!

五个扩展类(为啥是5个?答:增删改查,查有两个)

搭配GenericAPIView使用

1.ListModelMixin: 提供list方法快速实现列表视图

2.CreateModelMixin: 提供create方法快速实现创建资源的视图

3.RetrieveModelMixin 提供retrieve方法,可以快速实现返回一个存在的数据对象(需要传入pk)

4.UpdateModelMixin 提供update方法,可以快速实现更新一个存在的数据对象。 提供partial_update方法,可以实现局部更新

5.DestroyModelMixin 提供destroy方法,可以快速实现删除一个存在的数据对象

一个例子:


  1. class BookDetailView(mixins.RetrieveModelMixin, GenericAPIView):
  2. """使用GenericAPIView实现“获取单一图书信息”接口"""
  3. serializer_class = BookInfoSerializer # 指定序列化器
  4. queryset = BookInfo.objects.all() # 指定查询集
  5. def get(self, request, pk):
  6. """
  7. 获取单一图书信息
  8. GET /books/<pk>/
  9. :param request: Request类型的对象
  10. :return: JSON
  11. """
  12. return self.retrieve(request)

看到没有,函数里边只有一行代码了,简化了吧!明显看得出来,这个父类帮我们吧return之前的事情都做了

GenericAPIView搭配扩展类的使用的优势就显示出来了

我想说的是:这里还能简化!!!

1.CreateAPIView(等价于GenericAPIView+CreateModelMixin) 提供 post 方法 继承自: GenericAPIView、CreateModelMixin

2.ListAPIView 提供 get 方法 继承自:GenericAPIView、ListModelMixin

3.RetrieveAPIView 提供 get 方法 继承自: GenericAPIView、RetrieveModelMixin

4.DestoryAPIView 提供 delete 方法 继承自:GenericAPIView、DestoryModelMixin

5.UpdateAPIView 提供 put 和 patch 方法 继承自:GenericAPIView、UpdateModelMixin

6.RetrieveUpdateAPIView 提供 get、put、patch方法 继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

7.RetrieveUpdateDestoryAPIView 提供 get、put、patch、delete方法 继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

所以代码中的mixins.RetrieveModelMixin, GenericAPIView可以写成RetrieveAPIView

4.视图集父类1:ViewSet

那么能否继续优化呢?答案:能!!!

前边的父类仍需要写很多函数,这些函数定义仍然增加我们的工作量

ViewSet:将几个操作放在一起(前边的方法都是分开实现的)

list() 提供一组数据

retrieve() 提供单个数据

create() 创建数据

update() 保存数据

destory() 删除数据

ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get‘:‘list‘})的映射处理工作。

在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

如:


  1. class BookInfoViewSet(viewsets.ViewSet):
  2. def list(self, request):
  3. books = BookInfo.objects.all()
  4. serializer = BookInfoSerializer(books, many=True)
  5. return Response(serializer.data)
  6. def retrieve(self, request, pk=None):
  7. try:
  8. books = BookInfo.objects.get(id=pk)
  9. except BookInfo.DoesNotExist:
  10. return Response(status=status.HTTP_404_NOT_FOUND)
  11. serializer = BookInfoSerializer(books)
  12. return Response(serializer.data)

视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上

如:

url(r‘^books/$‘, BookInfoViewSet.as_view({‘get‘:‘list‘}),

url(r‘^books/(?P<pk>\d+)/$‘, BookInfoViewSet.as_view({‘get‘: ‘retrieve‘})

5.视图集父类2:GenericViewSet

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView。


  1. class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
  2. queryset = BookInfo.objects.all()
  3. serializer_class = BookInfoSerializer

设置url:


  1. url(r‘^books/$‘, views.BookInfoViewSet.as_view({‘get‘: ‘list‘})),
  2. url(r‘^books/(?P<pk>\d+)/$‘, views.BookInfoViewSet.as_view({‘get‘: ‘retrieve‘}))

6.视图集父类3:ModelViewSet

只需定义

queryset = BookInfo.objects.all()

serializer_class = BookInfoAllSerializer

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。


  1. class BookInfoViewSet(ModelViewSet):
  2. queryset = BookInfo.objects.all()
  3. serializer_class = BookInfoAllSerializer

7.视图集父类4:ReadOnlyModelViewSet

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin


  1. class BookInfoViewSet(ReadOnlyModelViewSet):
  2. """使用视图集实现返回列表和单一数据"""
  3. # 指定序列化器
  4. serializer_class = BookInfoSerializer
  5. # 指定查询集
  6. queryset = BookInfo.objects.all()
  7. # detail为False 表示路径名格式应该为 books/latest/
  8. @action(methods=[‘get‘], detail=False)
  9. def latest(self, request):
  10. """
  11. 自定义action: 返回最新的图书信息
  12. GET /books/latest/
  13. """
  14. # latest : 先将数据根据‘id‘倒叙,再取第0个
  15. book = BookInfo.objects.latest(‘id‘)
  16. serializer = self.get_serializer(book)
  17. return Response(serializer.data)

8.路由router

当我们完成上述工作后,发现路由默认5个,加上自己配置的有很多路由,每自定义一个新的方法时就得配置路由。

DRF提供了路由:Routers

快速实现路由 Routers主要有两个: SimpleRouter           DefaultRouter

DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

使用: register(prefix, viewset, base_name)

prefix 该视图集的路由前缀

viewset 视图集

base_name 路由名称的前缀

在路由文件中创建router对象,并注册视图集,最后把视图加到urlpatterns中 如:

# 给视图集定义路由

router = DefaultRouter()

router.register(r‘books‘, views.BookInfoViewSet)

# 将DRF生成的路由信息,添加到urlpatterns

urlpatterns += router.urls

原文地址:https://www.cnblogs.com/whkzm/p/12142151.html

时间: 2024-11-07 14:49:48

def --- DRF视图的详细用法的相关文章

【DRF视图】

目录 开始使用内置视图 请结合[DRF序列化]此文献中的数据文件及序列化文件来阅读如下代码. DRF视图为我们提供了非常简便的方法--内置了增删改查等一系列的操作. 我们只需在url中指定对应的方法,视图继承内置方法的类,即可实现两三行代码搞定一个请求. @ * 我们先看看仿照内置方法实现的** APIView视图文件: from rest_framework.views import APIView from rest_framework.response import Response fr

【DRF视图】 -- 2019-08-08 18:01:40

目录 开始使用内置视图 原文: http://106.13.73.98/__/61/ 请结合[DRF序列化]此文献中的数据文件及序列化文件来阅读如下代码. DRF视图为我们提供了非常简便的方法--内置了增删改查等一系列的操作. 我们只需在url中指定对应的方法,视图继承内置方法的类,即可实现两三行代码搞定一个请求. @ * 我们先看看仿照内置方法实现的** APIView视图文件: from rest_framework.views import APIView from rest_framew

文档/视图结构详细介绍

以单文档界面(SDI)应用程序为例,介绍MFC的文档/视图程序结构. 学习要求 理解文档/视图结构,可在AppWizard生成的SDI程序框架的基础上添加必要的代码,以生成自己的应用程序. 授课内容 大部分应用程序均要使用数据,其主要工作可以分为两部分:一是对数据的管理,如存储.复制和查询等任务,一是对数据的处理和输入输出,包括显示和打印.MFC提供了“文档/视图”结构支持这类应用程序. 12.1文档/视图概念 在文档/视图结构里,文档可视为一个应用程序的数据元素的集合,MFC通过文档类提供了大

超详细ofstream和ifstream详细用法

ofstream和ifstream详细用法 ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间(文章最末尾附上了MSDN中关于这两个函数的解释); 在C++中,有一个stream这个类,所有的I/O都以这个"流"类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符: 1.插入器(<<) 向流输出数据.比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<&quo

C++ ofstream和ifstream详细用法以及C语言的file用法

ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就是内存空间; 在C++中,有一个stream这个类,所有的I/O都以这个"流"类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符: 1.插入器(<<) 向流输出数据.比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"W

使用DRF视图集时自定义action方法

在我们用DRF视图集完成了查找全部部门,创建一个新的部门,查找一个部门,修改一个部门,删除一个部门的功能后,views.py的代码是这样子的: class DepartmentViewSet(ModelViewSet): queryset = Department.objects.all() serializer_class = DepartmentSerializer 现在需要新增一个功能,查询最新成立的部门. 这时,我们就需要自定义action方法了. 新增功能后的代码如下: class D

Display:Block 详细用法

根据CSS规范的规定,每一个网页元素都有一个display属性,用于确定该元素的类型,每一个元素都有默认的display属性值,比如div元素,它的默认display属性值为"block",成为"块级"元素(block-level):而span元素的默认display属性值为"inline",称为"行内"元素. 块级元素: 动占据一定矩形空间,可以通过设置高度.宽度.内外边距等属性,来调整的这个矩形的样子: 行内元素: 自己的

DOM Style样式对象的详细用法

DOM Style样式对象的详细用法 HTML Style样式比较复杂,相应访问.修改方法也有所差异.参考相关资料,整理如下. 典型Html文件如下,有三种定义方式. <head>     <style type="text/css">                /* 内部样式 */       h3 {color:green;}     </style>             <!-- 外部样式 style.css -->    

文件/目录权限设置命令chmod的详细用法

chmod是文件/目录权限设置的命令,在Linux中经常遇到,本博文以下总结chmod的详细用法. Linux/Unix的档案调用权限分为三级,即档案拥有者user.群组group.其他other.u表示该档案的拥有者,g表示与该档案的拥有者属于同一个群体(group)者,o表示其他以外的人,a表示这三者皆是. + 表示增加权限.- 表示取消权限.= 表示唯一设定权限. r表示可读取,w表示可写入,x表示可执行. 举例说明: (1).将档案file1.txt 设为所有人皆可读取: chmod u