当前位置:网站首页>drf view component
drf view component
2022-08-02 14:21:00 【Pasta with 42 concrete】
Python之drf视图组件
一、Local verification Global verification source code analysis
截取一段views.py里的代码
def post(self, request):
back_dic = {
'code': 200, 'msg': '新增成功', 'result': ''}
result = BookModelSerializer(data=request.data)
if not result.is_valid():
return Response(result.errors)
result.save() # 保存数据
back_dic['result'] = result.data
return Response(back_dic)
Inside the serialized class object pointis_valid(),It is to verify the validity of the deserialized data
…………
二、Serialization component source code analysis
序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象
序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找)
Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance)
再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs
当参数传过去,判断是方法就加括号执行,是属性就把值取出来
三、请求与响应
1、Request
REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象.
REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典[QueryDict]对象保存到Request对象中.
Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果
无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据.
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
相同,只是更换了更正确的名称而已.
3)drfConfigure the request format
# 通过配置,Set the encoding format supported by the backend interface,Three are supported by default
# 1、可以在项目的settings.py配置文件中配置,Call it this“全局配置”
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser', # json
'rest_framework.parsers.FormParser', # urlencoded
'rest_framework.parsers.MultiPartParser' # form-data文件格式
]
}
# 2、局部配置,Write class properties in the view class
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
parser_classes = [JSONParser,] # Local configuration defaults to this method only acceptedjson格式数据
2、Response
from rest_framework.response import Response
Response(data, status=None, template_name=None, headers=None, content_type=None)
1)返回数据
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会根据前端所需类型数据来设置该参数.
Status codes can be written with numbers,can also be importedstatus包,Write a constant for the status code
from rest_framework import status
# 如下使用
return Response(back_dic,status=status.HTTP_200_OK)
return Response(back_dic,status=status.HTTP_404_NOT_FOUND)
2)drf配置响应格式
REST framework提供了一个响应类Response
,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型.
REST framework提供了Renderer
渲染器,用来根据请求头中的Accept
(接收数据类型声明)来自动转换响应数据到对应格式.如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式.
可以在rest_framework.settings查找所有的drf默认配置项
# 全局配置
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [ # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
]
}
3)自己封装Response对象
1、In the future, I will use my own custom packageresponse
class APIResponse(Response):
def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None, **kwargs):
dic = {
'code': code, 'msg': msg}
if data:
dic['data'] = data
dic.update(kwargs) # 这里使用update
super(APIResponse,self).__init__(data=dic, status=status,
template_name=None, headers=headers,
exception=False, content_type=content_type)
2、使用
return APIResponse(code=100,msg='查询成功',data=ser.data,count=200,next='http://xxx.com')
四、两个视图基类
1、APIView
from rest_framework.views import APIView
APIView
是REST framework提供的所有视图的基类,继承自Django的View
父类.
APIView
与View
的不同之处在于:
- 传入到视图方法中的是REST framework的
Request
对象,而不是Django的HttpRequeset
对象; - 视图方法可以返回REST framework的
Response
对象,视图会为响应数据设置(render)符合前端要求的格式; - 任何
APIException
异常都会被捕获到,并且处理成合适的响应信息; - 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制.
在APIView
中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法.
class publish(APIView):
# 获取所有出版社接口
def get(self,request):
back_dic = {
'code':200,'msg':'查询成功','result':''}
res = models.Publish.objects.all()
result = PublishModelSerializer(instance=res,many=True)
back_dic['result'] = result.data
return Response(back_dic)
2、GenericAPIView[通用视图类]
from rest_framework.generics import GenericAPIView
继承自APIVIew
,主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持.通常在使用时,可搭配一个或多个Mixin扩展类.
''' There are two class properties queryset = Book.objects.all() # The data you want to serialize serializer_class = serializer.BookSerializer # The serialization class you want to use 三个方法 get_queryset() # 获取要序列化的数据 get_serializer() # Get the serialization class to use get_object() # 获取单条数据(一定要用pk,如果你想改,重写类属性lookup_field) '''
# 使用GenericAPIView 通用视图类
from rest_framework.generics import GenericAPIView
# 书籍 无参
class Book(GenericAPIView):
queryset = models.Book.objects.all() # 获取所有数据的queryset对象
serializer_class = BookModelSerializer # Get the serialized class to be used
# 获取所有图书接口
def get(self, request):
back_dic = {
'code': 200, 'msg': '查询成功', 'result': ''}
res = self.get_queryset() # 获取所有数据
result = self.get_serializer(instance=res, many=True) # 使用BookModelSerializer序列化类
back_dic['result'] = result.data
return Response(back_dic)
def post(self, request):
back_dic = {
'code': 200, 'msg': '新增成功', 'result': ''}
result = self.get_serializer(data=request.data)
if not result.is_valid():
return Response(result.errors)
result.save() # 保存数据
back_dic['result'] = result.data
return Response(back_dic)
class Book_param(GenericAPIView):
queryset = models.Book.objects.all() # 获取所有数据的queryset对象
serializer_class = BookModelSerializer # Get the serialized class to be used
def get(self,request,**kwargs):
back_dic = {
'code': 200, 'msg': '查询成功', 'result': ''}
res = self.get_object() # 获取单条数据
result = self.get_serializer(instance=res)
back_dic['result'] = result.data
return Response(back_dic)
def delete(self,request,**kwargs):
back_dic = {
'code': 200, 'msg': '删除成功'}
models.Book.objects.filter(**kwargs).delete()
return Response(back_dic)
def put(self,request,**kwargs):
back_dic = {
'code': 200, 'msg': '修改成功', 'result': ''}
res = self.get_object()
result = self.get_serializer(instance=res,data=request.data)
if result.is_valid() ==False:
return Response(result.errors)
result.save()
back_dic['result'] = result.data
return Response(back_dic)
五、五个视图扩展类
提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量.
1、ListModelMixin
列表视图扩展类,提供list(request, *args, **kwargs)
方法快速实现列表视图,返回200状态码.
该Mixin的list方法会对数据进行过滤和分页.
This method is to get all objects
源码:
class ListModelMixin:
""" List a queryset. """
def list(self, request, *args, **kwargs):
# 过滤
queryset = self.filter_queryset(self.get_queryset())
# 分页
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
# 序列化
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
2、CreateModelMixin
创建视图扩展类,提供create(request, *args, **kwargs)
方法快速实现创建资源的视图,成功返回201状态码.
如果序列化器对前端发送的数据验证失败,返回400错误.
源代码:
class CreateModelMixin:
""" Create a model instance. """
def create(self, request, *args, **kwargs):
# 获取序列化qi
serializer = self.get_serializer(data=request.data)
# 数据校验
serializer.is_valid(raise_exception=True)
# 调用perform_create方法保存,Other requirements can be rewritten laterperform_create方法
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {
'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {
}
3、RetrieveModelMixin
详情视图扩展类,提供retrieve(request, *args, **kwargs)
方法,可以快速实现返回一个存在的数据对象.
如果存在,返回200, 否则返回404.
源代码:
class RetrieveModelMixin:
""" Retrieve a model instance. """
def retrieve(self, request, *args, **kwargs):
# 获取单个对象,会检查对象的权限
instance = self.get_object()
# 序列化
serializer = self.get_serializer(instance)
return Response(serializer.data)
4、UpdateModelMixin
UPDATE Tried to extend the class,提供update(self, request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象
同时也提供partial_update(request, *args, **kwargs)
方法,可以实现局部更新.
成功返回200,序列化器校验数据失败时,返回400错误.
源代码:
class UpdateModelMixin:
""" Update a model instance. """
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
# 获取单个对象,会检查对象的权限
instance = self.get_object()
# 序列化
serializer = self.get_serializer(instance, data=request.data, partial=partial)
# 校验数据
serializer.is_valid(raise_exception=True)
# 调用perform_update方法保存数据,It can be rewritten later according to business needsperform_update方法
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {
}
return Response(serializer.data)
def perform_update(self, serializer):
serializer.save()
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
5、DestroyModelMixin
删除视图扩展类,提供destroy(request, *args, **kwargs)
方法,可以快速实现删除一个存在的数据对象.
成功返回204,不存在返回404.
源代码:
class DestroyModelMixin:
""" Destroy a model instance. """
def destroy(self, request, *args, **kwargs):
# 获取单个对象,会检查对象的权限
instance = self.get_object()
# 调用perform_destroy方法删除数据,It can be rewritten later according to business needsperform_update方法
self.perform_destroy(instance)
# 返回状态码
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
6、综合
# 使用GenericAPIView 通用视图类
from rest_framework.generics import GenericAPIView
# Use five attempts to extend the class
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
# 书籍 无参
class Book(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = models.Book.objects.all() # 获取所有数据的queryset对象
serializer_class = BookModelSerializer # Get the serialized class to be used
# 获取所有图书接口
def get(self, request):
# back_dic = {'code': 200, 'msg': '查询成功', 'result': ''}
# res = self.get_queryset() # 获取所有数据
# result = self.get_serializer(instance=res, many=True) # 使用BookModelSerializer序列化类
#
# back_dic['result'] = result.data
return self.list(request)
def post(self, request):
return self.create(request)
class Book_param(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = models.Book.objects.all() # 获取所有数据的queryset对象
serializer_class = BookModelSerializer # Get the serialized class to be used
def get(self,request,**kwargs):
return self.retrieve(self,request,**kwargs)
def delete(self,request,**kwargs):
return self.update(self,request,**kwargs)
def put(self,request,**kwargs):
return self.destroy(self,request,**kwargs)
六、GenericAPIView九个视图子类
1、ListAPIView
提供get方法(获取所有)
继承自:GenericAPIView,ListModelMixin
2、CreateAPIView
提供post方法
继承自:GenericAPIView,CreateModelMixin
3、RetrieveAPIView
提供get方法(获取单个)
继承自:GenericAPIView,RetrieveModelMixin
4、UpdateAPIView
提供update方法
继承自:GenericAPIView,UpdateModelMixin
5、DestroyAPIView
提供delete方法
继承自:GenericAPIView,DestroyModelMixin
6、ListCreateAPIView
提供get,put,patch方法
继承自:GenericAPIView,ListModelMixin,RetrieveModelMixin
7、RetrieveDestroyAPIView
提供get,delete方法
继承自:GenericAPIView,DestroyModelMixin
8、RetrieveUpdateAPIView
提供get,put,patch方法
继承自:GenericAPIView,RetrieveModelMixin,UpdateModelMixin
9、 RetrieveUpdateDestoryAPIView
提供get,put,patch,delete方法
继承自:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
10、总结
# 使用GenericAPIView 通用视图类
# from rest_framework.generics import GenericAPIView
# Extend the class with nine views
from rest_framework.generics import ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView,ListCreateAPIView,RetrieveUpdateAPIView,RetrieveUpdateDestroyAPIView
# 书籍 无参
class Book(ListCreateAPIView):
queryset = models.Book.objects.all() # 获取所有数据的queryset对象
serializer_class = BookModelSerializer # Get the serialized class to be used
class Book_param(RetrieveUpdateDestroyAPIView):
queryset = models.Book.objects.all() # 获取所有数据的queryset对象
serializer_class = BookModelSerializer # Get the serialized class to be used
七、视图集ViewSet
使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中
- list() 提供一组数据
- retrieve() 提供单个数据
- create() 创建数据
- update() 保存数据
- destory() 删除数据
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等.
视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上.如:
class BookInfoViewSet(viewsets.ViewSet):
def list(self, request):
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
try:
books = BookInfo.objects.get(id=pk)
except BookInfo.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
serializer = BookInfoSerializer(books)
return Response(serializer.data)
在设置路由时,我们可以如下操作
urlpatterns = [
path('books/', BookInfoViewSet.as_view({
'get':'list'}),
path('books/<int:pk>', BookInfoViewSet.as_view({
'get': 'retrieve'})
]
1、常用视图集父类
1、ViewSet
继承自APIView
与ViewSetMixin
,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等
ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:’list’})的映射处理工作.
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法.
2、GenericAPIView
使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写.但是Mixin扩展类依赖与GenericAPIView
,所以还需要继承GenericAPIView
.
GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView
与ViewSetMixin
,在实现了调用as_view()时传入字典(如{'get':'list'}
)的映射处理工作的同时,还提供了GenericAPIView
提供的基础方法,可以直接搭配Mixin扩展类使用.
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student4ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
url的定义
urlpatterns = [
path("students7/", views.Student4ViewSet.as_view({
"get": "list", "post": "create"})),
re_path("students7/(?P<pk>\d+)/", views.Student4ViewSet.as_view({
"get": "retrieve","put":"update","delete":"destroy"})),
]
3、ModelViewSet
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin.(五个视图扩展类)
4、ReadOnlyModelViewSet
继承自GenericViewSet
,同时包括了ListModelMixin、RetrieveModelMixin.
2、视图集中定义附加action动作
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作.
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
def login(self,request):
"""学生登录功能"""
return Response({
"message":"登录成功"})
url的定义
urlpatterns = [
path("students8/", views.StudentModelViewSet.as_view({
"get": "list", "post": "create"})),
re_path("students8/(?P<pk>\d+)/",
views.StudentModelViewSet.as_view({
"get": "retrieve", "put": "update", "delete": "destroy"})),
path("stu/login/",views.StudentModelViewSet.as_view({
"get":"login"})) # 自定义action动作
]
八、总结
#两个基类
APIView
GenericAPIView:有关数据库操作
类属性:queryset 和serializer_class
方法:self.get_queryset(),self.get_serializer()和self.get_object()
#5个视图扩展类(rest_framework.mixins)
CreateModelMixin:create方法创建一条
DestroyModelMixin:destory方法删除一条
ListModelMixin:list方法获取所有
RetrieveModelMixin:retrieve获取一条
UpdateModelMixin:update修改一条
#9个子类视图(rest_framework.generics)
CreateAPIView:继承CreateModelMixin,GenericAPIView,有post方法,新增数据
DestroyAPIView:继承DestroyModelMixin,GenericAPIView,有delete方法,删除数据
ListAPIView:继承ListModelMixin,GenericAPIView,有get方法获取所有
UpdateAPIView:继承UpdateModelMixin,GenericAPIView,有put和patch方法,修改数据
RetrieveAPIView:继承RetrieveModelMixin,GenericAPIView,有get方法,获取一条
ListCreateAPIView:继承ListModelMixin,CreateModelMixin,GenericAPIView,有get获取所有,post方法新增
RetrieveDestroyAPIView:继承RetrieveModelMixin,DestroyModelMixin,GenericAPIView,有get方法获取一条,delete方法删除
RetrieveUpdateAPIView:继承RetrieveModelMixin,UpdateModelMixin,GenericAPIView,有get获取一条,put,patch修改
RetrieveUpdateDestroyAPIView:继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView,有get获取一条,put,patch修改,delete删除
#视图集
ViewSetMixin:重写了as_view
ViewSet: 继承ViewSetMixin和APIView
GenericViewSet:继承ViewSetMixin, generics.GenericAPIView
ModelViewSet:继承mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet
ReadOnlyModelViewSet:继承mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet
边栏推荐
- Unit 14 Viewsets and Routing
- 云GPU(恒源云)训练的具体操作流程
- Unit 10 Continuous Tuning
- [ROS] The software package of the industrial computer does not compile
- Flask请求应用上下文源码分析
- vim复制粘贴_vim如何复制粘贴
- 第七单元 ORM表关系及操作
- Flask framework in-depth
- The most complete ever!A collection of 47 common terms of "digital transformation", read it in seconds~
- Raft对比ZAB协议
猜你喜欢
YOLOv7使用云GPU训练自己的数据集
MobileNet ShuffleNet & yolov5 replace backbone
Some impressions of the 519 plummet 2021-05-21
[ROS] The difference between roscd and cd
The specific operation process of cloud GPU (Hengyuan cloud) training
云GPU(恒源云)训练的具体操作流程
海明校验码纠错设计原理
Briefly write about the use and experience of PPOCRLabel
Cloin 控制台乱码
Linux: CentOS 7 install MySQL5.7
随机推荐
Cloin 控制台乱码
hsql是什么_MQL语言
The most complete ever!A collection of 47 common terms of "digital transformation", read it in seconds~
ping命令的使用及代码_通过命令查看ping路径
yolov5,yolov4,yolov3 mess
第七单元 ORM表关系及操作
AWVS工具介绍[通俗易懂]
replay视频播放器_怎么让手机音乐跟视频一起放
(ROS) (03) CMakeLists. TXT, rounding
[ROS] Introduction to common tools in ROS (to be continued)
[ROS] (04) Detailed explanation of package.xml
瑞吉外卖笔记——第08讲读写分离
Deep learning framework pytorch rapid development and actual combat chapter4
Flask-RESTful请求响应与SQLAlchemy基础
[ROS] The difference between roscd and cd
第八单元 中间件
yolov5 improvement (1) Add attention focus mechanism
What is the difference between web testing and app testing?
The IDEA of packaged jar package
Web Design (Beginners) [easy to understand]