ApiView的类属性

如下是ApiView所有的类属性,我们抽取一部分进行介绍:

可见这些类属性,都是使用drf配置文件的默认配置。

下列策略可以在全局设置 或者 在每一个视图类中设置。

允许依赖注入其他的设置文件, ApiView源码的settings类属性使测试更容易 (也就是不使用drf的api_settings)

  • renderer_classes: 用于设置视图类的响应格式。默认情况会有两种响应格式,一种是响应json字符串,一种是对浏览器的响应。
  • parser_classes:用于定义视图类能够解析的请求格式。默认情况下使用3个解析类进行解析,可以解析如下媒体类型:multipart/form-dataapplication/x-www-form-urlencodedapplication/json
  • authentication_classes:认证类相关配置
  • throttle_classes:频率类相关配置
  • permission_classes:权限类相关配置

复习:

# APIView跟之前的View区别
-传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
-视图方法可以返回REST framework的Response对象-
-任何APIException异常都会被捕获到,并且处理成合适的响应信息;
-在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制

drf 配置文件之查找顺序

在apiView中使用了drf配置文件的默认配置。以下是配置的查找顺序。

方式三:查找顺序(一般就用内置的即可)
1. 视图类 (局部配置)
2. django settings (全局配置)
3. drf api_settings (内置配置)
说明:
优先使用视图类中renderer_classes的配置,其次使用django项目配置文件settings中的配置,最后使用drf内置的api_settings的配置

在django的settings中应该按照如下格式写:

REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [ # 配置响应
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer',
],
'DEFAULT_PARSER_CLASSES': [ # 配置请求
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
}
# 注意:所有配置都写在一个REST_FRAMEWORK里面!

drf之请求

APIView之请求相关配置

# 为什么需要进行请求相关配置?
可以定制某些CBV只能只能接收json格式,不能接收其他格式。也就是为了自定义该接口可接受编码格式。 # 默认情况下
前端上传json request.data里面是 ---> python字典
前端上传urlencode\formdata request.data里面是 ---> QueryDict # 方式一,在继承自APIView及其子类的的视图类中配置(局部配置)
# 总共有三个:from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
parser_classes = [JSONParser,] # 方式二:在配置文件中配置(影响所有,全局配置)
-django有套默认配置,每个项目有个配置
-drf有套默认配置,每个项目也有个配置---》就在django的配置文件中
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
# 'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
# 'rest_framework.parsers.MultiPartParser',
],
} # 方式三:全局配了1个,某个视图类想要3个,怎么配?
-只需要在视图类,配置3个即可
-因为:先从视图类自身找,找不到,去项目的drf配置中找,再找不到,去drf默认的配置找 # 视图类方法中的request
-data
-__getattr__
-query_params

drf之响应

APIView之响应相关配置

# 为什么要在CBV中设置响应相关配置?
因为对于drf的响应,如果使用浏览器和postman访问同一个接口,Response返回的格式是不一样的
-drf做了个判断,如果是浏览器,好看一些,如果是postman只要json数据 # 方式一:在视图类中写(局部配置)
-两个响应类---》找---》drf的配置文件中找--》两个类
-from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class BookView(APIView):
renderer_classes=[JSONRenderer,] # 方式二:在项目配置文件中写(全局配置)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
} # 方式三:使用顺序(一般就用内置的即可)
1. renderer_classes
2. django settings
3. drf api_settings
说明:
优先使用视图类中renderer_classes的配置,其次使用django项目配置文件settings中的配置,最后使用drf内置的api_settings的配置

Response对象属性

# drf 的Response 源码分析
-from rest_framework.response import Response
-视图类的方法返回时,retrun Response ,走它的__init__, init中可以传什么参数
-Responses最终继承httpresponse. # Response init可以传的参数
def __init__(self,
data=None,
status=None,
template_name=None,
headers=None,
exception=False,
content_type=None) -data:之前咱们写的ser.data 可以是字典或列表,字符串---》序列化后返回给前端---》前端在响应体中看到的就是这个 -status: http响应的状态码,默认是200,你可以改
-drf在status包下,把所有http响应状态码都写了一遍,常量
-from rest_framework.status import HTTP_200_OK
-Response('dddd',status=status.HTTP_200_OK) -template_name:了解即可,修改响应模板的样子,BrowsableAPIRenderer定死的样子,后期公司可以自己定制 -headers:响应头,http响应的响应头 示例:header={'xxx':'yyy'} -content_type :响应编码格式,一般不动 # 重点:data,status,headers # 原生djagno,如何在响应头中加东西? '''
四件套 render,redirect,HttpResponse,JsonResponse
方法: 产生HttpResponse然后添加属性
'''
# 示例:
obj = HttpResponse('dddd')
obj['xxc'] = 'yyc'
return obj 响应头添加属性涉及知识 ---> 跨域

drf Response提供很多的状态码:

在status内将所有状态码都写了一遍:

视图类

from .models import Book
from .serializer import BookSerializer class BookView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data) def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
# 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors}) class BookDetailView(APIView):
def get(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books)
return Response(ser.data) def put(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors}) def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})

序列化类

### ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
# 跟表有关联
class Meta:
model = Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}

路由

urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookDetailView.as_view()),
]

基于GenericAPIview 写五个接口

如果需要再新写关于作者的五个接口 ----> 又需要写一个CBV:但是两个的区别在于 表模型 和 序列化类

这岂不是很麻烦?能不能通过继承的方式,优化代码?

于是就写了一个 GenericAPIview --继承于--> APIView ,以后可以基于这个类来写5个接口。

GenericAPIview必备设置

如果你想使用GenericAPIview,你需要从如下二种选择其一:

  1. 在视图类中设置如下属性 (常用)

    querysetserializer_class

  2. 重写GenericAPIview类的get_queryset()/get_serializer_class()方法

如果你重写了一个视图方法,那么重要的是 你应该调用get_queryset() 而不是直接的访问queryset属性。

因为queryset将只被设置一次,并且为了后续到来的所有请求,这个结果会被缓存。

总而言之,不要直接访问querysetserializer_class属性,而是使用GenericAPIview提供的各种方法获取。

查询所有

# 首先指定模型对象 和 序列化类
class BookView(GenericAPIView):
queryset = Book.objects.all()
# queryset = Book.objects 这样也是可行的
serializer_class = BookSerializer # 以下代码都是等效的
objs = Book.objects.all()
objs = self.get_queryset() # 以下代码都是等效的
ser = self.get_serializer(instance=objs, many=True)
BookSerializer(instance=objs, many=True)

get_queryset()

get_queryset方法得到视图中的列表对象!

这个列表对象必须是一个可迭代的,也可以是一个queryset对象。

默认使用self.queryset来获取(视图中的列表对象):

应该总是使用这个方法来获取,而不是直接调用self.queryset

get_queryset源码做了些什么事?

  1. 如果没有在视图类中写queryset属性,然后就调用get_queryset,会抛出异常。
  2. 获取我们设置的queryset属性,如果是Queryset对象,则调用all()方法,最后将我们设置的queryset类属性返回出去。

get_serializer()

使用get_serializer()方法可以返回序列化器的实例,此序列化器,被应用于校验、反序列化前端输入和序列化后端输出。

get_serializer源码做了些什么事?

  1. 通过get_serializer_class方法获取了我们在视图类中指定的序列化类

  2. 添加了一个'context'参数传入我们的序列化类。

    相当于BookSerializer(instance=objs, many=True, context={一些数据...})

get_serializer_class()

get_serializer_class方法基本上什么事情都没有做,直接将序列化器返回,有需求可以重写get_serializer_class。

可以实现:不同的接口使用的序列化类不一样。序列化使用某一个序列化类,反序列化用另一个序列化类。

重写:

查询一个

这里会根据传入的pk参数查询出对应的模型对象,

正常情况下写查询一个的接口我们需要手动写orm( 比如Book.objects.filter(pk=pk)),根据主键将对象查出来。

这里因为使用了GenericAPIview,他会自动帮我们查。

get_object()

就是通过pk参数和get_object方法将模型对象查询出来的。

返回应用于详细视图的对象实例。默认使用 lookup_field 参数过滤基本的查询集。

该方法可以被重写以提供更复杂的行为,例如基于多个 URL 参数的对象查找。

lookup_field属性

如果你想使用pk之外的对象查找方式,可以设置lookup_field。如果有更复杂的查找需求,可以重写get_object()

以下给出一个示例:

修改查询条件为书籍的名字:

filter_queryset()

可见在get_object方法中,调用了get_queryset()获取了我们放在视图中的queryset,然后使用了filter_queryset()对我们从数据库中获取的queryset进行了过滤操作。

关于filter_queryset的解释是:

给他一个queryset,他会使用任何一个你正在使用的后端过滤器,进行过滤。

self.filter_backends:由于我们类中没有配置,所以会指向GenericAPIview类中的filter_backends。

在GenericAPIview类中默认使用的是drf配置文件中指定的默认过滤器。

然后drf配置文件中,默认是不过滤:

所有总而言之,默认就是不过滤,但是我们可以通过在自己的视图类中写filter_backends属性,来指定过滤器。

新增一个

    def post(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})

修改一个

 def put(self, request, pk):
obj = self.get_object()
ser = self.get_serializer(instance=obj, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})

删除一个

  def delete(self, request, pk):
obj = self.get_object()
obj.delete()
return Response({'code': 100, 'msg': '删除成功'})

更多GenericAPIview 类属性

基本设置

  • queryset - 用于从视图返回对象的查询结果集。通常,你必须设置此属性或者重写 get_queryset() 方法。如果你重写了一个视图的方法,重要的是你应该调用 get_queryset() 方法而不是直接访问该属性,因为 queryset 将被计算一次,这些结果将为后续请求缓存起来。
  • serializer_class - 用于验证和反序列化输入以及用于序列化输出的Serializer类。 通常,你必须设置此属性或者重写get_serializer_class() 方法。
  • lookup_field - 用于执行各个model实例的对象查找的model字段。默认为 'pk'。 请注意,在使用超链接API时,如果需要使用自定义的值,你需要确保在API视图序列化类设置查找字段。
  • lookup_url_kwarg - 应用于对象查找的URL关键字参数。它的 URL conf 应该包括一个与这个值相对应的关键字参数。如果取消设置,默认情况下使用与 lookup_field相同的值。

配置文件相关

以下属性用于在与列表视图一起使用时控制分页。

  • pagination_class - 当分页列出结果时应使用的分页类。默认值与 DEFAULT_PAGINATION_CLASS 设置的值相同,即 'rest_framework.pagination.PageNumberPagination'

  • filter_backends - 用于过滤查询集的过滤器后端类的列表。默认值与DEFAULT_FILTER_BACKENDS 设置的值相同。

基于GenericAPIView + 5个视图扩展类

虽然使用了GenericAPIview类写五个接口,但是写的代码还是太多了,并没有减少代码呀!

CBV类中的方法 getpostputdelete代码都是重复的,是不是可以再进行优化?

drf的作者自然想到了这一点,他提供了5个视图扩展类,帮我们写了这一部分代码!

先导入五个视图扩展类:

from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin

查询所有

class BookView(GenericAPIView, ListModelMixin):
queryset = Book.objects
serializer_class = BookSerializer def get(self, request):
return self.list(request)

现在就只需要使用self.list调用ListModeMixin类中写的代码:

和我们之前写的差不多,先获取queryset然后将其传入序列化类。中间还进行了过滤,分页操作。

查询一个

class BookDetailView(GenericAPIView, RetrieveModelMixin):
queryset = Book.objects
serializer_class = BookSerializer def get(self, request, pk): # 注意要传入这个pk
return self.retrieve(request)

对应关系

这样很方便的就可以实现五个接口,我们只需要知道方法直接的对应关系就行了:

ListModelMixin      -->  list      -->  查询所有
RetrieveModelMixin --> retrieve --> 查询一个
CreateModelMixin --> create --> 新增一个
UpdateModelMixin --> update --> 修改一个
DestroyModelMixin --> destroy --> 删除一个

代码:

class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects
serializer_class = BookSerializer def get(self, request):
return self.list(request) def post(self, request):
return self.create(request) class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects
serializer_class = BookSerializer def get(self, request, pk):
return self.retrieve(request) def put(self, request, pk):
return self.update(request) def delete(self, request, pk):
return self.destroy(request)

虽然已经简化了代码,但是其实还是有重复的部分比如这些请求方法,之后还会进行封装。

继承具体视图类写5个接口

什么叫具体视图类?Concrete View Classes

也就是drf作者已经帮你把CBV需要写的接口代码都写好了,打包成了一个个类,你只需要直接继承这些类,你的视图类就会有相应的接口,是不是很神奇 ~ ~

drf提供如下具体视图类:

注意:没有DestroyUpdateAPIView

直接上代码:

from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView

class BookView(ListCreateAPIView):  # 查询所有 新增一个
queryset = Book.objects
serializer_class = BookSerializer class BookDetailView(RetrieveUpdateDestroyAPIView): # 查询一个 修改一个 删除一个
queryset = Book.objects
serializer_class = BookSerializer

使用ModelViewSet写五个接口

之前我们使用两个CBV写五个接口的原因是:

查询一个和查询所有都是使用get请求,为了解耦合,避免在类中的get方法中写太多代码,所以将其拆成两个CBV。

而使用ModelViewSet可以实现,一个视图类写5个接口。

from rest_framework.viewsets import ModelViewSet

class BookView(ModelViewSet):
queryset = Book.objects
serializer_class = BookSerializer

参考

【Django drf】视图类APIView之五层封装 ApiView的类属性 drf配置文件的更多相关文章

  1. 『无为则无心』Python面向对象 — 51、私有成员变量(类中数据的封装)

    目录 1.私有成员变量介绍 (1)私有成员变量概念 (2)私有成员变量特点 (3)私有成员变量体验 2.属性私有化工作原理 3.定义成员变量的标识符规范 4.私有成员变量的获取和设置方式 1.私有成员 ...

  2. 067.Python框架Django之DRF视图类

    一 关于视图类的一下概念 drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. ...

  3. Django通用视图APIView和视图集ViewSet的介绍和使用

    原 Django通用视图APIView和视图集ViewSet的介绍和使用 2018年10月21日 14:42:14 不睡觉假扮古尔丹 阅读数:630   1.APIView DRF框架的视图的基类是 ...

  4. Django通用视图APIView和视图集ViewSet的介绍和使用(Django编程-1)

    1.APIView DRF框架的视图的基类是 APIView APIView的基本使用和View类似 Django默认的View请求对象是 HttpRequest,REST framework 的请求 ...

  5. drf03 drf视图中提供的请求类和响应类

    drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. Django REST ...

  6. day73:drf:drf视图相关类&路由Routers&创建虚拟环境

    目录 1.APIView 2.GenericAPIView:通用视图类 3.5个视图扩展类:ListModelMixin,CreateModelMixin,RetrieveModelMixin,Upd ...

  7. drf04 drf视图类

    REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写. 1.2个视图基类 1.1. APIView rest_framework.views.APIView APIView ...

  8. 068.Python框架Django之DRF视图集使用

    一 视图集与路由的使用 使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中: list() 提供一组数据 retrieve() 提供单个数据 create() 创建数据 update() ...

  9. DRF视图-基类

    2个视图基类 REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写. 为了区分上面请求和响应的代码,我们再次创建一个新的子应用: python manage.py star ...

  10. DRF 视图组件

    目录 DRF 视图组件 视图组件大纲 两个视图基本类 五个扩展类 九个子类视图 视图集 常用视图集父类 魔法类 一览表 DRF中视图的"七十二变" 第一层:基于APIview的五个 ...

随机推荐

  1. SpringBoot 过滤器和拦截器

    过滤器 实现过滤器需要实现 javax.servlet.Filter 接口.重写三个方法.其中 init() 方法在服务启动时执行,destroy() 在服务停止之前执行. 可用两种方式注册过滤器: ...

  2. windows下 安装docker

    一.Docker 1.什么是docker 对比 特性 容器 虚拟机 启动 秒级 分钟级 磁盘使用 一般为MB 一般为GB 性能 接近原生 弱于 系统支持量 单机支持上千个容器 一般几十个 2. 使用d ...

  3. 将自己的组件打包发布到npm

    在项目中有些组件在各个项目中都会调用,那么将组件发布到npm ,用到的项目去下载,这样会省去一些不必要的麻烦. 将组件发布到npm 中的步骤 做个记录 1.项目的创建,我这里使用 vue init w ...

  4. laravel的_token传值 ; header中传_token

    laravel框架中只要是涉及到post传值都需要传 _token ,这是框架中为了防止crsf攻击所做的安全措施,那么我们用到ajax中的post 方式传值时,也需要在所传数据中添加一个_token ...

  5. 随笔——安卓手机调试微信网页,x5错误页

    如果打开debugx5.qq.com提示您使用的不是x5内核 那么先打开debugmm.qq.com/?forcex5=true 再打开http://debugtbs.qq.com 将进入下面这个页面 ...

  6. python解释器下载与安装指导手册

    python解释器下载与安装指导手册 1.python解释器 1.1下载地址 1 https://www.python.org/ 1.2.python解释器下载 1.3.python解释器主流版本 p ...

  7. Training: Stegano I

    原题链接:http://www.wechall.net/challenge/training/stegano1/index.php 很明显,这是一道图像隐写题,因为他说的 我们右键图片,点击其他窗口打 ...

  8. Opengl ES之YUV数据渲染

    YUV回顾 记得在音视频基础知识介绍中,笔者专门介绍过YUV的相关知识,可以参考: <音视频基础知识-YUV图像> YUV数据量相比RGB较小,因此YUV适用于传输,但是YUV图不能直接用 ...

  9. # Android网络请求(4) 网络请求框架Volley

    Android网络请求(4) 网络请求框架Volley Volley是Google在2013年5月15日到17日在旧金山Moscone中心举办网络开发者年会中推出的Android异步网络加载框架和图片 ...

  10. 【第7篇】AI语音交互原理介绍

    本章主要介绍AI语音交互的原理,包括语音交互的流程以及各流程节点所涉及的相关知识,如语音采集.语音识别.自然语言处理.语音合成等. 2.1 AI语音交互 AI语音交互通俗点说就是人与机器间进行语音理解 ...