rest_framework之组件大长今
功能导入快捷查询:
from rest_framework import serializers # 序列化
from rest_framework.routers import SimpleRouter,DefaultRouter # 路由
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer # 限制返回页面数据还是json数据
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination # 分页
from rest_framework.versioning import URLPathVersioning, # 版本控制,还有放在请求头中的AcceptHeaderVersioning
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser # 解析器
from rest_framework.permissions import BasePermission # 权限
from rest_framework.views import APIView # 视图
from rest_framework.viewsets import ModelViewSet # 高级封装视图
from rest_framework.response import Response
from rest_framework.status import HTTP_404_NOT_FOUND # 错误码
from app01 import serializer
from rest_framework.request import Request
from rest_framework.exceptions import ValidationError # 序列化错误返回前端
drf # APIView的流程分析
# -APIView:dispatch---》包装了request,执行了认证,权限,频率
# -原生request对象
# -里面有个GET(以get形式提交的数据),以get形式提交的数据,都拆到environ内部,django把数据取出来转成了QueryDict的对象
# -session不是原生request对象的属性,在中间件中放进去的(django.contrib.sessions.middleware.SessionMiddleware) # -drf的Request类
# -data(post提交的数据,json格式,urlencoded,fromdata编码方式的数据)
# -data的类型并不是固定的,可能是QueryDict,也可能是字典
# -query_params--->原生的GET
# -重写了__getattr__ 对象.属性 当属性不存在就会执行该方法
return getattr(self._requset,'属性')
FILES # 上传的文件
# -序列化
# -序列号使用:
# -写一个类继承:Serializer或者ModelSerializer
# -类内写字段
name=serialzier.CharField(source='字段,方法,对象.字段')
# -如果是ModelSerializer:
class Meta:
model=表
fields=(字段,字段,)
# -如果想重写字段
-在Meta上面或者下面:name=serialzier.CharField(source='字段,方法,对象.字段')
# -SerializerMethodField
-对应着一个方法:get_字段名(self,obj),方法返回值是什么,这个字段就是什么
# -在视图中使用
-实例化产生一个序列化类的对象(instance=要序列化的对象,data=json格式,many=True)
# -对象.data 是个字典格式 # -反序列化的使用
# -json格式转成对象,保存到数据库
# -在保存之前一定要先调用对象.is_valid()
# -Serializer的子类,需要重写create方法,自己写保存逻辑
# -ModelSerializer 直接save
# -校验(局部和全局)
# -validate_字段名字 局部校验
# -validate 全局校验
# -源码分析
# -序列化类实例化的时候:
# -many=True的时候,生成的是列表中放了一个个的序列号化对象
# -many=False 的时候,生成的是一个序列化对象
# -__new__控制的
# -校验的源码部分
-调用了bookser.is_valid方法才走校验----》内部走了self.run_validation方法(找该方法一定要从根上找)---》Serializer类中找到了run_validation方法---》
重点的地方:self.to_internal_value(局部钩子)/self.validate(全局钩子)
Serializer类中找到了to_internal_value,去对象内部反射validate_字段名的方法,如果不为None,直接执行,于是就执行了咱们自己写的局部校验的函数 # -序列化对象.data 的时候做了什么事
-执行Serializer内的data方法---》又执行了父类(BaseSerializer)的data方法---》执行self.to_representation(其实执行的是Serializer内的to_representation方法)
最终执行的是每个字段对象的get_attribute方法---》找字段对象的该方法--》在Field中找到了该方法
---》执行了get_attribute(instance, self.source_attrs)---》self.source_attrs:每个字段source后面指定的根据.切分后的列表(publish.name:就会被分成[publish,name])
如果是方法会执行方法,如果是字段,通过反射取出值
# -认证
# -使用(所有人都必须会)、
# -写一个认证类(继承BaseAuthentication)
# -重写authenticate方法,把request对象传入
# -能从request对象中取出用户携带的token,根据token判断是否登录过
# -如果登录过,返回两个值 user对象,token对象
# -如果没有登录过抛异常
# -全局使用
# -在settings中配置
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.MyAuths.MyAuth",]
}
# -局部使用
# -在视图类中配置:
authentication_classes=[MyAuth,]
# -局部禁用:
# -在视图类中配置:
authentication_classes=[]
-update_or_create() 有就更新,没有就创建
参数:key=value,default={'token':token}
# -uuid的使用:生成一个唯一的随机字符串
# -源码分析(大部分人会)
# -APIView中的dispatch---》self.initial(认证,频率,权限)---》self.perform_authentication(认证)---》本质又调用了新的request对象的user方法
--》request.user内部执行了:self._authenticate(注意self是新的request对象)-----》循环拿到一个个认证类的对象,执行对象的authenticate方法,传入request对象
---》一个个认证类的对象是在reuqest对象实例化的时候传入的---》APIView中的get_authenticators,通过列表推导式生成一个个的认证类对象,然后传入request对象中
# -权限
# -使用(所有人都必须会)
# -写一个权限类
class MyPermision(BasePermission):
message = '不是超级用户,查看不了'
def has_permission(self,request,view):
if request.user.user_type==1:
return True
else:
return False
# -局部使用
# -在视图类中配置:
permission_classes=[MyPermision,]
# -全局使用
# -在setting中配置
'DEFAULT_PERMISSION_CLASSES':['自定义的权限类']
# -局部禁用:
permission_classes=[]
# -返回的提示是中文:
message=中文
# -源码分析
def check_permissions(self, request):
#我猜 一个个对象的列表
for permission in self.get_permissions():
if not permission.has_permission(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
)
# -视图
# -基本写法(略)
# -第二中写法
class PublishView(CreateModelMixin,ListModelMixin,GenericAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers
-写get和post,在其中调用父类的create或者list方法 # -第三种写法:
class PublishView(ListCreateAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers class PublishDetailView(RetrieveUpdateDestroyAPIView):
queryset = models.Publish.objects.all()
serializer_class = PublishSerializers # -第四种写法(两个视图类合成一个)
class PublishView(ModelViewSet):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers
# -ViewSetMixin重写了as_view方法,路由配置就改了,可以写成映射的形式{get:get_one} # -as_view方法内部执行效果
# 通过反射的取值跟赋值,完成映射,根据请求方式执行对应的方法(比如:get请求执行get_one方法,在路由中配置{get:getone}) # 3 __new__方法的使用
class Test():
def __init__(self,name):
print('xxxxxxx')
self.name=name
def __new__(cls, *args, **kwargs):
#返回一个空对象
#现在返回一个字符串对象,内部会去调用字符串对象的__init__方法
# return 'justin'
return object.__new__(cls) t=Test('lqz')
# print(t.name) ####频率组件#####
# -使用:
# -第一步,写一个频率类,继承SimpleRateThrottle
from rest_framework.throttling import SimpleRateThrottle
#重写get_cache_key,返回self.get_ident(request)
#一定要记住配置一个scop=字符串
class Throttle(SimpleRateThrottle):
scope = 'lxx'
def get_cache_key(self, request, view):
return self.get_ident(request)
# -第二步:在setting中配置
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_RATES':{
'lxx':'3/m'
}
}
# -局部使用
# -在视图类中配置:
throttle_classes=[Throttle,]
# -全局使用
# -在setting中配置
'DEFAULT_THROTTLE_CLASSES':['自己定义的频率类'],
# -局部禁用
throttle_classes=[]
# 频率组件分析:
# -核心源代码:
def check_throttles(self, request):
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
self.throttled(request, throttle.wait()) # -自定义的频率类:详解代码views.py 25行开始 # -SimpleRateThrottle源码 # -url控制
# -基本路由写法:咱们一直写的
# -第二种写法(必须继承只要继承了ViewSetMixin):
# url(r'^publish/$', views.PublishView.as_view({'get':'list','post':'create'})),
# url(r'^publish\.(?P<format>\w+)$', views.PublishView.as_view({'get':'list','post':'create'})),
# url(r'^publish/(?P<pk>\d+)$', views.PublishView.as_view({'get':'retrieve','delete':'destroy','put':'update'})),
# -第三种(自动生成路由,必须继承ModelViewSet):
-SimpleRouter 自动生成两条路由
from rest_framework.routers import SimpleRouter,DefaultRouter
router=SimpleRouter()
router.register('publish',views.PublishView)
# 路由
url(r'', include(router.urls)),
-DefaultRouter自动生成四条路由
from rest_framework.routers import SimpleRouter,DefaultRouter
router=DefaultRouter()
router.register('publish',views.PublishView)
# 路由
url(r'', include(router.urls)), # -解析器(一般不需要动,项目最开始全局配置一下就可以了)
# -作用是控制我的视图类能够解析前端传过来的格式是什么样的
# -全局使用:
# 在setting中配置:
REST_FRAMEWORK = {
"DEFAULT_PARSER_CLASSES":[
'rest_framework.parsers.JSONParser',
]
}
# -全局使用:
# -在视图类中:
parser_classes=[JSONParser,] # -源码流程:
# -当调用request.data的时候去执行解析方法----》根据传过来的编码方式选择一个解析器对象,调用解析器对象的parser方法完成解析
# -响应器
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
# -不用动,就用全局配置即可
# -全局使用:
# -在setting中配置
'DEFAULT_RENDERER_CLASSES':[JSONRenderer,BrowsableAPIRenderer]
# -局部使用:
# -在视图类中配置:
renderer_classes = [JSONRenderer, BrowsableAPIRenderer] # -版本控制
# -作用用于控制版本
# -全局使用:
# -在setting中配置:
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值)
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
'VERSION_PARAM': 'version' # URL中获取值的key
# -路由需要修改
-url(r'^(?P<version>[v1|v2]+)/test/', views.Test.as_view()),
# -在视图类中就可以通过:request.version取出当前访问哪个版本,相应的取执行相应版本的代码 # -分页
from rest_framework.pagination import CursorPagination,LimitOffsetPagination,PageNumberPagination
# 1 常规分页
# -基本使用:
-page=PageNumberPagination # 实例化产生对象
# -返回值=page.paginate_queryset(ret,request,self):ret是要分页的所有数据,自动调用Response
# -再序列化,序列化该返回值
# -四个参数
#每页显示多少条
page.page_size=3
#查询指定查询哪一页的key值
page.page_query_param='xxx' #前端控制每页显示多少条的查询key值比如size=9,表示一页显示9条
page.page_size_query_param='size'
#控制每页最大显示多少,size如果传100,最多也是显示10
page.max_page_size=10
# 2 偏移分页
# -基本使用:
page=LimitOffsetPagination实例化产生对象
# -返回值=page.paginate_queryset(ret,request,self):ret是要分页的所有数据,
# -再序列化,序列化该返回值 # -四个参数:
#从标杆位置往后取几个,默认取3个,我可以指定
page.default_limit=3
#每次取得条数
page.limit_query_param='limit'
#标杆值,现在偏移到哪个位置,如果offset=6 表示当前在第6条位置上,往后取
page.offset_query_param='offset'
#最大取10条
page.max_limit=10
# 3 cursor游标方式
# -基本使用:
-page=CursorPagination实例化产生对象
# -返回值=page.paginate_queryset(ret,request,self):ret是要分页的所有数据,
# -再序列化,序列化该返回值 # -三个参数:
#每页显示的大小
page.page_size=3
#查询的key值
page.cursor_query_param='cursor'
# 按什么排序
page.ordering='id'
#-注意:get_paginated_response:调用这个方法返回的数据中会有总条数,上一页地址,下一页地址
rest_framework之组件大长今的更多相关文章
- django rest_framework 序列化组件详解
为什么要用序列化组件 当我们做前后端分离的项目,我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 那么我们给前端数据的时候都要转成json格式,那就需要对我们从数据库拿到 ...
- bootstrap轮播组件,大屏幕图片居中效果
在慕课网学习bootstrap轮播组件的时候,了解到轮播的图片都放在了类名为item下的img中 视频中老师对图片自适应采用给图片img设置width=100%完成,然而这样自适应处理图片在不同屏幕中 ...
- rest_framework登录组件,权限组件
昨日回顾: -HyperlinkedIdentityField(用来生成url),传三个参数 -实例化序列化类的时候,BookSerializer(ret, many=True, context={' ...
- Django的rest_framework认证组件之全局设置源码解析
前言: 在我的上一篇博客我介绍了一下单独为某条url设置认证,但是如果我们想对所有的url设置认证,该怎么做呢?我们这篇博客就是给大家介绍一下在Rest_framework中如何实现全局的设置认证组件 ...
- Django的rest_framework认证组件之局部设置源码解析
前言: Django的rest_framework组件的功能很强大,今天来我来给大家剖析一下认证组件 下面进入正文分析,我们从视图开始,一步一步来剖析认证组件 1.进入urls文件 url(r'^lo ...
- rest_framework -- 认证组件
#####认证组件##### 一.认证是什么就不说了,某些网页必须是用户登陆之后,才能访问的,所以这时候就需要用上认证组件. 你不用rest_framework的认证组件也行,这种认证的话,完全可以自 ...
- rest_framework序列化组件
一.Django自带的序列化组件 ==>对象序列化成json格式的字符串 from django.core import serializers from django.core import ...
- Django之REST_FRAMEWORK 认证组件
Django之DRF之认证组件 # from rest_framework.views import APIView # APIView 中的 dispatch 中 执行的 self.initial( ...
- rest_framework 认证组件 权限组件
认证组件 权限组件 一.准备内容 # models class User(models.Model): name = models.CharField(max_length=32) pwd = mod ...
随机推荐
- springboot项目上传文件大小限制问题
1.报错信息: Error parsing HTTP request header Note: further occurrences of HTTP header parsing errors wi ...
- 富文本编辑器+可粘贴word内容
Chrome+IE默认支持粘贴剪切板中的图片,但是我要发布的文章存在word里面,图片多达数十张,我总不能一张一张复制吧? 我希望打开文档doc直接复制粘贴到富文本编辑器,直接发布 感觉这个似乎很困难 ...
- 2-set奶牛议会
Description 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会.议会以“每头牛 都可以获得自己想要的”为原则,建立了下面的投票系统: M只到场的奶牛 (1 & ...
- Ubuntu 14.04 卸载通过源码安装的库
cd cere-solvermkdir buildcd buildcmake ..sudo makesudo make install 卸载通过以上方式源码安装的库 再次进入buildsudo mak ...
- Go开发环境安装与环境变量配置
1.Go安装包下载 https://studygolang.com/dl 2.安装 Windows平台下,直接下一步即可完成安装. 3.配置环境变量 系统变量 安装完成后,在系统变量的Path一栏,会 ...
- Java基础系列 - 子类继承父类,调用父类的构造函数
package com.test7; public class test7 { public static void main(String[] args) { Son son = new Son(1 ...
- formidable处理提交的表单或图片文件的简单介绍
一般来说,客户端向服务端提交数据有GET和POST这两种方式,在之前的文章node.js当中的http模块与url模块的简单介绍当中我们可以知道通过req.url与url模块的配合处理可以快速得到客户 ...
- meshing-划分圆柱结构化网格
原视频下载地址:https://yunpan.cn/cqjeckrzEpVkY 访问密码 eb5d
- Hibernate HQL和QBC
OID查询 一.什么是OID查询 根据对象的OID主键进行检索 二.OID查询方式 1. get方法 当get()方法被调用的时候就会立即发出SQL语句 并且返回的对象也是实际的对象 使用get()和 ...
- 实现一个微信小程序组件:文字跑马灯效果
marquee.json { "component": true, "usingComponents": {} } marquee.wxml <!--co ...