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 Responsefrom rest_framework.status import HTTP_404_NOT_FOUND # 错误码from app01 import serializerfrom 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 Trueelse: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 = PublishSerializersclass 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=namedef __new__(cls, *args, **kwargs):#返回一个空对象#现在返回一个字符串对象,内部会去调用字符串对象的__init__方法# return 'justin'return object.__new__(cls)t=Test('lqz')# print(t.name)####频率组件###### -使用:# -第一步,写一个频率类,继承SimpleRateThrottlefrom 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,DefaultRouterrouter=SimpleRouter()router.register('publish',views.PublishView)# 路由url(r'', include(router.urls)),-DefaultRouter自动生成四条路由from rest_framework.routers import SimpleRouter,DefaultRouterrouter=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,最多也是显示10page.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:调用这个方法返回的数据中会有总条数,上一页地址,下一页地址
转载于:https://www.cnblogs.com/dongxixi/p/11151924.html
rest_framework之组件大长今相关推荐
- 大长今人物系列:宿命中的孤独灵魂——崔今英(转载)
<大长今>人物系列:宿命中的孤独灵魂--崔今英 作者:绿犀牛[@more@]在长今所有的同龄人中,惟有崔今英拥有可以和她一较长短的天分.在某些方面,今英甚至比长今更有智慧.面对不同阵营的对 ...
- 大长今人物系列:长今的心理课——医女张德(转载)
作者:绿犀牛 (张德语录: 看起来是个好材料,就是太罗嗦了 把那些药材芯子去掉,如果你不做,我就照样开给病人吃,他们的心脏会有个大窟窿 有些人身体没病,只是心里有病,给他们药丸是安抚他们的心 凭我的力 ...
- 不看遗憾啊,韩版《大长今》中文音译,天才之作!
韩流袭来,一部大长今让中国人终于看到了韩国电视剧的罗里八嗦,但是主题歌却是一首反映中国一段野史的颂歌,歌曲表达了对山东大汉武松为兄报仇的英雄事 迹,几经反复,地狱耶稣终于破解了歌曲密码...... 最 ...
- 摘自《大长今励志启示》
因果定律--有因才会有果(1.2集) "看一个人现在有什么样的结果,你就可以知道他过去曾经种下了什么种子,凡事都先有了引发事件的原因,才会产生事件本身的结果." <大长今&g ...
- 大长今(汤灿版) 歌词
大长今主题曲内地版 演唱:汤灿 天多高 路多长 心有多大 千江水 千江月 何处是家 朝为露 暮为雨 若即若离 冷的风 暖的风 付之潮汐 (第二段) 天多高 路多长 心有多大 天之涯 海之角 处处是家 ...
- 《大长今》分集剧情介绍(上)
<大长今>分集剧情介绍(1-30集)[@more@]第一集 天寿奉皇令到废后尹氏家中赐予死药.回家途中,不幸跌落山谷,幸遇道士因而得救,性命无碍,道士预言天寿未来的命运将会是坎坷怪离,天寿 ...
- 为什么《大长今》是湖南卫视引入的?
今天同事一个哥们问了身在上海的湖南人的我一个奇怪的问题: 为什么<大长今>是湖南卫视引入的?为什么不是央视或者东方卫视? 当我表示不知道的时候,这哥们想出来一个很奇怪的理论: 他说他听说是 ...
- 电影《大长今》励志启示
人天生就会追求并满足两大欲望――一个是追求感官的快乐:一个是追求成功的教育.这两种人性的追求,与生俱来,任何人都无法阻挡. ...
- □ 影片名:《武大郎版大长今》(9225) 在线播放
□ 影片名:<武大郎版大长今>(9225) 在线播放 武大郎版大长今
最新文章
- UI设计师培训入门都需要学习什么技术?
- SCSI协议与存储的发展
- Anaconda系列:conda是什么?conda与pip的区别是什么?
- metasploit 漏洞评级翻译
- 得到目标元素距离视口的距离以及元素自身的宽度与高度(用于浮层位置的动态改变)...
- T-Sql 实现类似访问数组变量的操作
- 关于微信支付的退款那些事
- 我的BERT!改改字典,让BERT安全提速不掉分(已开源)
- 【jQuery】学习整理(一) 认识jQuery
- neo4j︱图数据库基本概念、操作罗列与整理(一)
- 单模光纤和多模光纤的区别,及光纤收发机(光电收发器)的介绍
- RemapKey等:小巧实用的键盘映射工具
- js 获取当天23点59分59秒 时间戳
- 如何用HTML和css实现拼图,怎样使用DIV+CSS实现拼图
- 电脑复制粘贴不了怎么办?
- UNIX时间戳的UTC(协调世界时)
- 7、Spring事务配置下篇
- 希尔伯特《几何学基础》的章节目录
- 云堡垒机相关概念汇总说明
- 【电机学】【公式速查】感应电动机、异步电动机