Django DRF ViewSet(十)
一、Request和Response
- Request
REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的**Request**类的对象。
REST framework 提供了**Parser**解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到**Request**对象中。
#DRF中的请求导入方式
from rest_framework.request import Request
Request.data #请求数据
Request.query_params====>Django.GET
常用属性
1).data
`request.data` 返回解析之后的请求体数据。类似于Django中标准的`request.POST`和 `request.FILES`属性,但提供如下特性:
- 包含了解析之后的文件和非文件数据
- 包含了对POST、PUT、PATCH请求方式解析后的数据
- 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
2).query_params
`request.query_params`与Django标准的`request.GET`相同,只是更换了更正确的名称而已。
2. Response
REST framework提供了一个响应类`Response`,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。
REST framework提供了`Renderer` 渲染器,用来根据请求头中的`Accept`(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。
#DRF中的响应导入方式
from rest_framework.response import Response
Response(data=Response.data,status=200,template_name=None,headers=None,content_type=None)
`data`数据不要是render处理之后的数据,只需传递python的内建类型数据即可,REST framework会使用`renderer`渲染器处理`data`。
`data`不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用`Serializer`序列化器序列化处理后(转为了Python字典类型)再传递给`data`参数。
参数说明:
- `data`: 为响应准备的序列化处理后的数据;
- `status`: 状态码,默认200;
- `template_name`: 模板名称,如果使用`HTMLRenderer` 时需指明;
- `headers`: 用于存放响应头信息的字典;
- `content_type`: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
常用属性:
1).data传给response对象的序列化后,但尚未render处理的数据
2).status_code状态码的数字
3).content经过render处理后的响应数据
- 视图
2.1 两个基类
1) APIView
from rest_framework.views import APIView
APIView是REST framework提供的所有视图的基类,继承自Django的View父类。
APIView与View的不同之处在于:
(1)传入到视图方法中的是REST framework的`Request`对象,而不是Django的`HttpRequeset`对象;
(2)视图方法可以返回REST framework的`Response`对象,视图会为响应数据设置(render)符合前端要求的格式;
(3)任何`APIException`异常都会被捕获到,并且处理成合适的响应信息;
(4)在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
支持定义的属性:
authentication_classes 列表或元祖,身份认证类
permissoin_classes 列表或元祖,权限检查类
throttle_classes 列表或元祖,流量控制类
在APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。
使用APIView实现增删改查所有图书:
views.py文件
################1.APIView视图###############################
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
# from django.views import View
# 使用APIView实现增删改查所有图书:
#继承APIView
class BookListAPIView(APIView):"""列表视图"""def get(self,request):#1.查询所有的图书all=BookInfo.objects.all()# 2.序列化数据,把模型对象转换成字典# instance 默认参数# many=True 显示多个数据#构造序列对象ser=BookInfoSerializer(instance=all,many=True)# print(ser.data)# response =Response(ser.data)# print(response.data) #响应对象未渲染处理的数据# print(response.content) # 处理后要响应给前端的数据# return response#响应return Response(ser.data)passdef post(self,request):'''添加数据'''#获取前端传入请求参数data=request.data#使用序列化器进行反序列哈ser=BookInfoSerializer(data=data)#校验 raise_exception显示错误消息ser.is_valid(raise_exception=True)#保存ser.save()#响应return Response(ser.data,status=status.HTTP_201_CREATED)pass
#继承APIView
class BookDataAPIView(APIView):'''详情视图 '''def get(self, request,pk):'''查询指定的模型对象=>必须指定id'''try:book=BookInfo.objects.get(id=pk)except BookInfo.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)# 构造序列化器对象ser =BookInfoSerializer(instance=book)# 响应return Response(ser.data)passdef put(self,request,pk):'''更新指定的模型对象=>必须指定id,需要校验'''try:book=BookInfo.objects.get(id=pk)except BookInfo.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)# 构造序列化器对象,获取前端传入的请求体数据ser = BookInfoSerializer(instance=book,data=request.data)#校验ser.is_valid(raise_exception=True)#保存ser.save()#响应return Response(ser.data)passdef delete(self,request,pk):'''删除指定的模型对象=>必须指定id''''''查询指定的模型对象=>必须指定id'''try:book = BookInfo.objects.get(id=pk)except BookInfo.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)#删除book.delete()return Response(status=status.HTTP_204_NO_CONTENT)
urls.py文件
#APIView视图path('books/',views.BookListAPIView.as_view()), #查询所有的图书数据, 类视图;注意:as_view()re_path(r'^books/(?P<pk>\d+)/$',views.BookDataAPIView.as_view()) #查询详情数据, 类视图;注意:as_view() 必须有()
]
效果:
删除之后,再查看:
2) GenericAPIView
from rest_framework.generics import GenericAPIView
继承自APIVIew,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。
源码如下:
支持定义的属性:
(1) 列表视图与详情视图通用:
queryset 列表视图的查询集
serializer_class 视图使用的序列化器
(2) 列表视图使用:
pagination_class 分页控制类
filter_backends 过滤控制后端
(3) 详情页视图使用:
lookup_field 查询单一数据库对象时使用的条件字段,默认为'`pk`'
lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同
常用方法:
- get_queryset(self) 返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回`queryset`属性,可以重写
- get_serializer(self, *args, **kwargs) 返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。
- get_object(self) 返回详情视图所需的模型类数据对象,默认使用`lookup_field`参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。
使用GenericAPIView实现增删改查所有图书:
views.py文件
################2.GenericAPIView视图###############################
from rest_framework.generics import GenericAPIView
class BookGenericAPIView(GenericAPIView):'''列表查询'''# 指定查询集'数据来源'queryset =BookInfo.objects.all()# 指定序列化器类serializer_class =BookInfoSerializer#查询方法def get(self,request):# 获取数据集find=self.get_queryset()# 返回序列化器对象ser=self.get_serializer(find,many=True)return Response(ser.data)def post(self, request):'''添加数据'''# 获取前端传入请求参数data = request.data# 使用序列化器进行反序列哈ser = BookInfoSerializer(data=data)# 校验 raise_exception显示错误消息ser.is_valid(raise_exception=True)# 保存ser.save()# 响应return Response(ser.data, status=status.HTTP_201_CREATED)class BookDataGenericAPIView(GenericAPIView):'''详情视图'''queryset = BookInfo.objects.all()serializer_class = BookInfoSerializerdef get(self,request,pk):'''根据id查询数据'''book=self.get_object()ser=self.get_serializer(book)return Response(ser.data)passdef put(self, request, pk):'''根据id更新数据'''book = self.get_object()#请求数据ser = self.get_serializer(book,request.data)#校验ser.is_valid(raise_exception=True)#保存ser.save()return Response(ser.data)passdef delete(self, request, pk):'''根据id删除数据,有可能发生异常'''try:book = self.get_object()except BookInfo.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)# 删除模型对象book.delete()return Response(status=status.HTTP_204_NO_CONTENT)pass
urls.py文件
# GenericAPIView视图path('booksg/', views.BookGenericAPIView.as_view()), # 查询所有的图书数据, 类视图;注意:as_view()re_path(r'^booksg/(?P<pk>\d+)/$', views.BookDataGenericAPIView.as_view()), # 查询详情数据, 类视图;注意:as_view() 必
]
2.2五个扩展类
- ListModelMixin :列表视图
源码:
views.py
from rest_framework.mixins import ListModelMixin
from rest_framework.generics import GenericAPIView #指定过滤化器queryset
class BookListModelMixin(ListModelMixin,GenericAPIView):'''列表视图'''#指定查询集 -数据来源queryset=BookInfo.objects.all()#指定序列化器serializer_class = BookInfoSerializerdef get(self,request):return self.list(request)
urls.py
# ListModelMixin
path('books_lmm/',views.BookListModelMixin.as_view())
2.CreateModelMixin:创建资源的视图
源码:
views.py
from rest_framework.mixins import CreateModelMixin
class BookCreateModelMixinView(CreateModelMixin,ListModelMixin,GenericAPIView):'''创建视图'''#指定查询集 -数据来源queryset=BookInfo.objects.all()#指定序列化器serializer_class = BookInfoSerializer#查询def get(self,request):return self.list(request)#添加def post(self,request):return self.create(request)urls.py
#CreateModelMixin
path('books_cmm/',views.BookCreateModelMixinView.as_view()),
发生异常;
RuntimeError: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/books_cmm/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
解决:
访问时不应该访问ip/books,
而应该访问ip/books/ 少了一个斜杠
3. RetrieveModelMixin 详情视图
源码:
views.py
from rest_framework.mixins import RetrieveModelMixin
class BookRetrieveModelMixinView(RetrieveModelMixin,GenericAPIView):'''详情视图'''#指定查询集 -数据来源queryset=BookInfo.objects.all()#指定序列化器serializer_class = BookInfoSerializer#查询def get(self,request,pk):return self.retrieve(request)urls.py
# RetrieveModelMixin
re_path(r'^books_xmm/(?P<pk>\d+)/$', views.BookRetrieveModelMixinView.as_view()), # 查询详情数据, 类视图;注意:as_view() 必
4 UpdateModelMixin: 更新视图
源码:
views.py
from rest_framework.mixins import UpdateModelMixin
class BookUpdateModelMixinView(UpdateModelMixin,RetrieveModelMixin, GenericAPIView):'''更新视图'''# 指定查询集 -数据来源queryset = BookInfo.objects.all()# 指定序列化器serializer_class = BookInfoSerializer# 查询一个def get(self, request,pk):return self.retrieve(request,pk)# 更新def put(self, request,pk):return self.update(request,pk)urls.py
#UpdateModelMixin
re_path(r'^books_umm/(?P<pk>\d+)/$',views.BookUpdateModelMixinView.as_view()),
5 DestroyModelMixin:删除视图
源码:
views.py
from rest_framework.mixins import DestroyModelMixin
class BookDestroyModelMixinView(DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin, GenericAPIView):'''删除视图'''# 指定查询集 -数据来源queryset = BookInfo.objects.all()# 指定序列化器serializer_class = BookInfoSerializer# 查询一个def get(self, request,pk):return self.retrieve(request,pk)# 更新def put(self, request,pk):return self.update(request,pk)# 删除def delete(self, request,pk):return self.destroy(request,pk)Urls.py
# DestroyModelMixin
re_path(r'^books_umm/(?P<pk>\d+)/$',views.BookDestroyModelMixinView.as_view()),
2.3 子类视图
2.4视图集ViewSet
使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
- GET: list() 提供一组数据
- GET: retrieve() 提供单个数据
- POST :create() 创建数据
- PUT :update() 更新数据
- PATCH: partail_update, 更新部分数据
- DELETE:destory() 删除数据
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上
from rest_framework.viewsets import ViewSet
class BookViewSet(ViewSet):'''视图集'''def list(self,request):'''展示列表数据'''#获取数据all=BookInfo.objects.all()#序列化ser=BookInfoSerializer(all,many=True)#返回数据return Response(ser.data)def retrieve(self,request,pk):'''获取单个数据'''try:book=BookInfo.objects.get(id=pk)except BookInfo.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)ser=BookInfoSerializer(book)return Response(ser.data)#视图集 ViewSet
#as_view中传入字典参数: 第一个参数:get,post,put,delete等等; 第二个参数:关联的方法名
#as_view中不能定义相同的请求
path('booksv/', views.BookViewSet.as_view({"get": "list"})),
re_path(r'^booksv/(?P<pk>\d+)/$',views.BookViewSet.as_view({"get":"retrieve"})),
2.4.1 ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
##########################视图集################
from rest_framework.viewsets import ViewSet
class BookViewSet(ViewSet):'''视图集'''def list(self,request):'''展示列表数据'''#获取数据all=BookInfo.objects.all()#序列化ser=BookInfoSerializer(all,many=True)#返回数据return Response(ser.data)def retrieve(self,request,pk):'''获取单个数据'''try:book=BookInfo.objects.get(id=pk)except BookInfo.DoesNotExist:return Response(status=status.HTTP_404_NOT_FOUND)ser=BookInfoSerializer(book)return Response(ser.data)#视图集 ViewSet
#as_view中传入字典参数: 第一个参数:get,post,put,delete等等; 第二个参数:关联的方法名
#as_view中不能定义相同的请求
path('booksv/', views.BookViewSet.as_view({"get": "list"})),
re_path(r'^booksv/(?P<pk>\d+)/$',views.BookViewSet.as_view({"get":"retrieve"})),
2.4.2视图集中定义附加action动作
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。
添加自定义动作需要使用`rest_framework.decorators.action`装饰器。
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
- methods: 该action支持的请求方式,列表传递
- detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
True 表示使用通过URL获取的主键对应的数据对象
False 表示不使用URL获取主键
##########################ModelViewSet################
from rest_framework.decorators import action
from rest_framework.viewsets import ModelViewSet
class BookViewSetAction(ModelViewSet):queryset = BookInfo.objects.all()serializer_class = BookInfoSerializer@action(methods=['get'],detail=False)def later(self,request):'''最新的图书信息'''# 获取最后一本书book =BookInfo.objects.latest('id')serializer=self.get_serializer(book)return Response(serializer.data)# detail为True,表示要处理具体与pk主键对应的BookInfo对象# books/pk/read/@action(methods=['put'],detail=True)def readCount(self,request,pk):"""修改图书的阅读量数据"""book =self.get_object()book.read_count=request.data.get('read_count')book.save()serializer=self.get_serializer(book)return Response(serializer.data)#ModelViewSet 注意:遵循ViewSet的规则,必须传字典参数哦!!否则发生错误!!
# ypeError: The `actions` argument must be provided when calling `.as_view()` on a ViewSet. For example `.as_view({'get': 'list'})`
#视图集中包含附加action的
path('books_m/', views.BookViewSetAction.as_view({'get': 'later'})),
re_path(r'^booksm/(?P<pk>\d+)/read/$', views.BookViewSetAction.as_view({'put':'readCount'})),
http://127.0.0.1:8000/booksm/13/read/
2.5. DefaultRouter与SimpleRouter的区别
DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。`DefaultRouter继承自SimpleRouter`
而使用SimpleRouter则会报错
Django DRF ViewSet(十)相关推荐
- Django学习之十: staticfile 静态文件
目录 Django学习之十: staticfile 静态文件 理解阐述 静态文件 Django对静态文件的处理 其它方面 总结 Django学习之十: staticfile 静态文件 理解阐述 静态文 ...
- Django DRF 两种接口安全机制及其配置
Django DRF 两种接口安全机制及其配置 接口安全机制,用于设置和管理用户调用接口时的权限问题.此处介绍最常用的两种接口安全机制及其配置. 1 使用之前 先生成接口文档 便于测试 1.1 安装依 ...
- 快速上手Django(六) -Django之Django drf 序列化器Serializer类
文章目录 快速上手Django(六) -Django之Django drf 序列化器Serializer类 1. 背景 2. 使用思路 3. 代码demo 4. [重要]序列化类 ModelSeria ...
- Django 基础(13)-Django drf 序列化器类to_representation和to_internal_value(处理返回的日期格式)、序列化类 ModelSerializer
文章目录 一.Django drf 序列化 1. 背景 2. 使用思路 3. 代码demo 4. [重要]序列化类 ModelSerializer 5. DRF序列化器to_representatio ...
- Django 基础(12)-Django drf 分页查询(批量查询)、自定义分页器
文章目录 Django drf 分页查询(批量查询) PageNumberPagination:普通分页 Django 自定义分页器 自定义批量查询的返回结构 LimitOffsetPaginatio ...
- Django笔记三十八之发送邮件
这一篇笔记介绍如何在 Django 中发送邮件. 在 Python 中,提供了 smtplib 的邮件模块,而 Django 在这个基础上对其进行了封装,我们可以通过 django.core.mail ...
- Django DRF API
Django 基本使用 前后端分离开发模式 1.1 前后端分离前 1.2 前后端分离前存在的一些问题 • PC.APP.Pad等多端流行 • 前后端开发职责不清晰:各司其职,最大程度减少开发难度,方便 ...
- Django框架(十九)—— drf:序列化组件(serializer)
序列化组件 # 模型层 from django.db import modelsclass Book(models.Model): nid = models.AutoField(primary_key ...
- Django REST framework(十)路由集routers的使用
Django REST framework(九)-视图集ViewSet.GenericViewSet.ModelViewSet.ReadOnlyModelViewSet_simpleyako的博客-C ...
最新文章
- 定义分销渠道(distribution channel)
- 无锁并发的CAS为何如此优秀?
- CSS框架+响应式设计
- GitHub 标星 5.7w,如何用 Python 实现所有算法?
- mui多层tab切换上拉加载的实现
- atitit.LimeSurvey 安装 attilax 总结
- java入门第二天如何使用Elipse
- 计算机网络强制100M,网络连通性故障分析与排除二例
- 应用时间序列分析案例操作--基于SAS软件,以北京市1980-2009年降水量为对象
- JAVA项目中枚举和字典表,枚举与字典表的选择
- docker应用篇(6):安装Uptime Kuma监控
- C语言之出圈游戏(详解)
- 开场白——第一篇博客
- from用法 prepare_MySQL之prepare用法
- 10行命令60秒快速定位性能瓶颈
- 刷新率属于计算机的显示性能指标吗,显示器性能指标(菜鸟必看)
- 哒哒哒~~今天说 事务的隔离级别和传播特性
- 【xla】六、【构图阶段】xlaRunOp
- 垃圾分类对生活的有什么好处
- wireshark过滤器
热门文章
- 网页三剑客,html/css/javascript
- 计算机柜里 do dl代表什么,dl是什么意思(你知道AI、ML和DL分别代表什么吗?)...
- gmt转换北京时间 java_java GMT 日期转换 | 学步园
- 图像处理----美白
- 类脑计算:让人工智能走得更远
- python网络爬虫--项目实战--scrapy爬取人人车(5)
- 达特茅斯计算机专业师资力量如何,达特茅斯学院(Dartmouth College)计算机科学Computer Science专业排名第126-150位(2021年THE世界大学商科排名)...
- operator=函数.
- 纯CSS实现beautiful的3D动画
- python3安装pip