一、请求

1 定义

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

由于这个Request类内部重写了__getattr__方法,所以原来的request类的方法在新的request也可以点出来使用

2 常用属性

1).data

request.data 返回解析之后的请求体数据。类似于Django中标准的request.POSTrequest.FILES属性,但提供如下特性:

  • 包含了解析之后的文件和非文件数据
  • 包含了对POST、PUT、PATCH请求方式解析后的数据
  • 利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据

2).query_params

request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。

总结:在drf中基本上使用的数据都是request.data,因为django原生的request不会解析json数据

二、响应

1 Response

rest_framework.response.Response

drf提供了一个响应类Response,该类在构造响应对象的时候,响应会被转化(render)成符合前端需求的类型,这一步在drf重写的dispatch源码中有。

但是我们可以发现,如果我们是浏览器发起请求得到的是一个页面,如果是postman发起请求,得到的直接就是json数据,这是内部帮我们判断了一下。

drf也提供了修改默认值的方法,让我们可以在前端也直接接受json格式的数据

# 在settings.py中添加(这是默认的,不加也是这样)
# 默认原来的出处在drf的settings里
# 当发起响应的时候,会先在我们项目的settings内找,找不到再去默认的里找
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
# 注释掉下面任意一条就只能返回另一条了
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}

2 构造方法

Response(data, status=None, template_name=None, headers=None, content_type=None)

参数说明:

  • data: 为响应准备的序列化处理后的数据,通常放一个字典;
  • status: 状态码,默认200;
  • template_name: 模板名称,如果使用HTMLRenderer 时需指明,通常不用;
  • headers: 用于存放响应头信息的字典,放一个字典;
  • content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。

3 状态码

为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。

1)信息告知 - 1xx

HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS

2)成功 - 2xx

HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS

3)重定向 - 3xx

HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT

4)客户端错误 - 4xx

HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS

5)服务器错误 - 5xx

HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

三、视图

1 基类视图 APIView

apiview是drf中所有视图类的基类,它继承自djangoview

在前几篇中有对应的源码分析,apiview和view的区别:

  • 传入到视图类中的request是drf新封装的,是在原来request上扩展的,所以原来的属性方法也能直接使用
  • 返回的response,会在apiview内部渲染成符合前端要求的格式(json或者html)
  • 任何APIException都会被捕获,并且处理成合适的响应信息
  • 在执行apiview内的dispatch方法,会对请求身份认证,权限检查,流量控制

支持定义的类属性

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

APIView实现5个常用的api接口

class StudentAPI(APIView):
def get(self,request,pk):
obj = models.Student.objects.filter(pk = pk).first()
ser_boj = ser.StudentSerializer(obj)
return JsonResponse(ser_boj.data) def put(self,request,pk):
back_dic = {'code':200,'msg':'成功'}
obj = models.Student.objects.filter(pk = pk).first()
ser_obj = ser.StudentSerializer(obj,request.data)
if ser_obj.is_valid():
ser_obj.save()
back_dic['data'] = ser_obj.data
else:
back_dic['code'] = 100
back_dic['msg'] = '出错'
back_dic['error_msg'] = ser_obj.errors
return JsonResponse(back_dic)
def delete(self,request,pk):
obj = models.Student.objects.filter(pk=pk).first()
if obj:
obj.delete()
back_dic = {'code': 200, 'msg': '成功','data':{}}
else:
back_dic = {'code': 100, 'msg': '失败','error_msg':'用户不存在'}
return Response(back_dic) class StudentsAPI(APIView):
def post(self,request):
# print(request.data)
back_dic = {'code': 200, 'msg': '成功'}
obj = ser.StudentSerializer(data = request.data)
if obj.is_valid():
obj.save()
back_dic['data'] = obj.data
else:
back_dic['code'] = 100
back_dic['msg'] = '错误'
back_dic['error_msg'] = obj.errors return (back_dic) def get(self,request):
obj = models.Student.objects.all()
obj_ser = ser.StudentSerializer(obj,many=True)
back_dic = {'code':200,'msg':'正确','data':obj_ser.data}
return Response(back_dic,status=201)

2 通用视图类 GenericAPIView

继承自APIView,主要增加了统一视图类的查询集和序列化器,作为给下面的Mixin扩展类的执行提供方法支持,通常在使用的时候回搭配Mixin扩展类使用

内部提供的关于序列化器的属性和方法

  • 属性:serializer_class指明视图使用的序列化器

  • 这个属性对应的方法:

    • get_serializer_class(self)

    • 这个方法返回的是是序列化器类,如果我们这个视图类中要根据不同情况使用不同的序列化器类的时候即可重写这个方法

    • def get_serializer_class(self):
      if self.request.user.is_staff:
      return FullAccountSerializer
      return BasicAccountSerializer
    • 这个方法如果不重写,默认会返回我们在属性里定义的serializer_class指定的序列化器类

    • get_serializer(self, args, *kwargs)

    • 这个方法返回的是序列化器对象,主要用来提供给后面介绍的Mixin扩展类使用,如果我们想在视图类中获取序列化器对象,也可以直接使用这个方法

    • 内部传参和调用序列化器类一样

    • stu_ser = self.get_serializer(instance = self.get_queryset(),many = True)
      # data 接受修改的数据
    • 注意,该方法在提供序列化器对象的时候,会向序列化器对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。

      • request 当前视图的请求对象
      • view 当前请求的类视图对象
      • format 当前请求期望返回的数据格式
  • 属性:queryset:指明使用的数据查询集

  • 方法:get_queryset(self)

    • 返回视图使用的查询集,通常提供给Mixin扩展类使用

    • 若返回的模型对象不存在,返回404

    • 该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

      举例:

      # url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
      class BookDetailView(GenericAPIView):
      queryset = BookInfo.objects.all()
      serializer_class = BookInfoSerializer def get(self, request, pk):
      book = self.get_object() # get_object()方法根据pk参数查找queryset中的数据对象
      serializer = self.get_serializer(book)
      return Response(serializer.data)

    其他可以设置的属性

  • pagination_class 指明分页控制类

  • filter_backends 指明过滤控制后端

基于GenericAPIView写5个api

# get全部,post单个
class StudentsGenericAPI(GenericAPIView):
queryset = models.Student.objects.all()
serializer_class = ser.StudentModelSerializer
def get(self,request):
stu_ser = self.get_serializer(instance = self.get_queryset(),many = True)
return Response(stu_ser.data)
def post(self,request):
print(request.data)
stu_ser = self.get_serializer(data=request.data)
if stu_ser.is_valid():
stu_query = stu_ser.save()
stu_ser = self.get_serializer(stu_query)
return Response(stu_ser.data)
return Response(stu_ser.errors) # get单个,put单个,del单个
class StudentGenericAPI(GenericAPIView):
queryset = models.Student.objects
serializer_class = ser.StudentModelSerializer
def get(self,request,pk):
stu_ser = self.get_serializer(self.get_queryset().filter(pk=pk).first())
return Response(stu_ser.data)
def put(self,request,pk):
stu_ser = self.get_serializer(self.get_queryset().filter(pk=pk).first(),data=request.data)
if stu_ser.is_valid():
stu_ser.save()
return Response(stu_ser.data)
return Response(stu_ser.errors)
def delete(self,request,pk):
self.get_queryset().filter(pk=pk).first().delete()
return Response({'msg':'删除成功'})

序列化器类:

from rest_framework import serializers

from students.models import Student

class StudentModelSerializer(serializers.ModelSerializer):
class Meta:
model= Student
fields = "__all__" class StudentModel2Serializer(serializers.ModelSerializer):
class Meta:
model= Student
fields = ("name","class_null")

3 扩展类Mixin

# 基于视图扩展类写的api
# 相比于只用Generic,把5个api方法都在对应的视图扩展类中写了,只要继承调用即可
# 对应关系如下
# list:get全部,create:post,update:put,destroy:delete,retrieve:get单个
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin class Students2API(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = models.Student.objects
serializer_class = ser.StudentModelSerializer
def get(self,request):
return self.list(request)
def post(self,request):
return self.create(request)
class Student2API(GenericAPIView,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin):
queryset = models.Student.objects
serializer_class = ser.StudentModelSerializer
def put(self,request,pk):
return self.update(request,pk)
def get(self,request,pk):
return self.retrieve(request,pk)
def delete(self,request,pk):
return self.destroy(request,pk)

4 GenericAPIView的视图子类

#GenericAPIView的视图子类 9个
from rest_framework.generics import CreateAPIView,ListAPIView,UpdateAPIView,RetrieveAPIView,DestroyAPIView,ListCreateAPIView,RetrieveUpdateDestroyAPIView,RetrieveDestroyAPIView,RetrieveUpdateAPIView
# 视图子类在5个扩展类的基础上,把我们函数的方法写到内部去了
# 所以下面我们只要继承这些视图类,然后定义查询集和序列化器就能根据请求的不同自动调用对应的视图函数
# 对应关系如下
# 单个的对应关系,list:get全部,create:post,update:put,destroy:delete,retrieve:get单个
# 多个的对应关系,ListCreate:get全部+post,RetrieveUpdateDestroy:get单个+put+delete
# 多个的对应关系,RetrieveDestroy:get单个+delete,RetrieveUpdate:get单个+put
class Students3API(ListCreateAPIView):
queryset = models.Student.objects
serializer_class = ser.StudentModelSerializer
class Student3API(RetrieveUpdateDestroyAPIView):
queryset = models.Student.objects
serializer_class = ser.StudentModelSerializer

5 视图集

1) ViewSet

继承自APIViewViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

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

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

总结:扩展性高,自动化程度低

2)GenericViewSet

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

GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIViewViewSetMixin,在实现了调用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。

# 使用ModelViewSet写5个api,url需要修改
# ModelViewSet继承了5中扩展视图类,所以只要配置好就可以使用5个对应的api方法
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet,ViewSetMixin
class Students4API(ModelViewSet):
queryset = models.Student.objects
serializer_class = ser.StudentModelSerializer # urls
url(r'^student4/$',views.Students4API.as_view(actions={
'get':'list','post':'create'
})),
url(r'^student4/(?P<pk>\d+)',views.Students4API.as_view(actions={
'get':'retrieve','put':'update','delete':'destroy'
})),

4)ReadOnlyModelViewSet

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

# ReadOnlyModelViewSet对应get全部和get单个
class Student5API(ReadOnlyModelViewSet):
queryset = models.Student.objects
serializer_class = ser.StudentModelSerializer # urls
url(r'^student5/$',views.Student5API.as_view(actions={'get':'list'})),
url(r'^student5/(?P<pk>\d+)',views.Student5API.as_view(actions={'get':'retrieve'})),

四、视图类继承关系

视图扩展类Mixin都是顶级继承

ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin 都继承自object

ViewSetMixin 它是视图集的顶级父类,所有视图集最终都继承它

GenericAPIView视图子类都继承它,也继承对应关系的视图扩展Mixin类

CreateAPIView,ListAPIView,UpdateAPIView,RetrieveAPIView,DestroyAPIView,ListCreateAPIView,RetrieveUpdateDestroyAPIView,RetrieveDestroyAPIView,RetrieveUpdateAPIView

通用视图子类继承关系

视图基类继承关系

GenericAPIView----》APIView----》View

视图集继承关系

xxx视图集继承关系查找方式:

我们可以先看名字,如果结尾是ViewSet,可以确定是一个视图集

普通视图集---》GenericViewSet----》ViewSetMixin

普通视图集也会继承对应的Mixin扩展类

比如ReadOnlyModelViewSet,是只读视图集,就是只有get全部和get单个的方法,那它必定还继承ListModelMixin和RetrieveModelMixin扩展类

总结:继承关系只要知道继承的方式就很好判断,所以要明白什么是视图集,什么是基类视图,什么是扩展类,通用视图和通用视图子类

drf请求、响应与视图的更多相关文章

  1. DRF的请求响应组件

    目录 DRF的请求响应组件 请求模块(request) 概念 request源码简单分析 响应模块(response) 概念 使用方法 response源码简单分析: 解析模块(parse) 概念 使 ...

  2. 序列化多表操作、请求与响应、视图组件(子类与拓展类)、继承GenericAPIView类重写接口

    今日内容概要 序列化多表操作 请求与相应 视图组件 内容详细 1.序列化多表操作 模型类 models.py中 # 新建django项目 # 创建表 模型类models.py中: from djang ...

  3. DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render

    DRF框架    全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...

  4. drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析

    admin后台注册model  一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...

  5. Django(48)drf请求模块源码分析

    前言 APIView中的dispatch是整个请求生命过程的核心方法,包含了请求模块,权限验证,异常模块和响应模块,我们先来介绍请求模块 请求模块:request对象 源码入口 APIView类中di ...

  6. python---django请求-响应的生命周期(FBV和CBV含义)

    Django请求的生命周期是指:当用户在访问该url路径是,在服务器Django后台都发生了什么. 客户端发送Http请求给服务端,Http请求是一堆字符串,其内容是: 访问:http://crm.o ...

  7. 第一篇 Flask基础篇之(配置文件,路由系统,模板,请求响应,session&cookie)

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后 ...

  8. laravel基础课程---8、laravel响应和视图(响应是什么)

    laravel基础课程---8.laravel响应和视图(响应是什么) 一.总结 一句话总结: 就是向请求返回的响应数据(一般为html(视图),当然也可以是变量值):所有的路由及控制器必须返回某个类 ...

  9. 基于请求响应的MVC框架调用分析

    一.使用Servlet来处理请求响应 当client提交数据之后.接着发送请求,请求被封装成对象,server接收到请求,依据请求的URL.来推断将请求对象交由哪个Servlet处理. 在servle ...

随机推荐

  1. 实验四 Linux系统搭建C语言编程环境

    项目 内容 这个作业属于那个课程 <班级课程的主页链接> 这个作业的要求在哪里 <作业要求链接地址> 学号-姓名 17043220-万文文 作业学习目标 1).Linux系统下 ...

  2. watch监听事件

    Vue.js 监听属性 watch,可以通过 watch 来响应数据的变化.以下实例通过使用 watch 实现计数器: <div id="app">           ...

  3. (二)log4j 配置详解

    原文链接:https://blog.csdn.net/liupeifeng3514/article/details/79625013 1.配置根logger log4j.rootLogger = de ...

  4. CentOS安装部署Mysql 5.7

    1,如果没有安装wget,先安装yum -y install wget 2,下载MySQL官方的 Yum Repositorywget http://repo.mysql.com/mysql57-co ...

  5. yii2.0数据库操作

    User::find()->all(); 此方法返回所有数据: User::findOne($id); 此方法返回 主键 id=1 的一条数据(举个例子): User::find()->w ...

  6. jmeter关联的五种方式

    [脚本准备] 这里,我们用dummy取样器来模拟服务器的返回,通过关联获取name的值,然后接口取这个name的值,这就我们就简单模拟了请求间的依赖关系 在取样器中添加dummy取样器 搜索的关键字是 ...

  7. django OperationalError: unable to open database file 创建数据库

  8. Docker Dockerfile 指令详解与实战案例

    Dockerfile介绍及常用指令,包括FROM,RUN,还提及了 COPY,ADD,EXPOSE,WORKDIR等,其实 Dockerfile 功能很强大,它提供了十多个指令. Dockerfile ...

  9. 我是如何从零学习开发一款跨平台桌面软件的(Markdown编辑器)

    [本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究.若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!] 原始冲动 最近一 ...

  10. Magicodes.IE在.NET Core中通过请求头导出多种格式文件

    前言 在2.2里程碑中我们增加了一些新的功能,正如标题所写通过请求头进行导出我们不同格式的文件.下面我们来看一下如何使用.通过这种方式无论是对我们的数据多用途,还是说对我们的数据校验都做到了轻松易配. ...