DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)
| url控制 |
第二种写法(只要继承了ViewSetMixin)
url(r'^pub/$',views.Pub.as_view({'get':'list','post':'create'})), #获取所有记得路由后面加$结束符 #pub/?format=json
url(r'^pub\.(?P<format>\w+)$',views.Pub.as_view({'get':'list','post':'create'})), #pub.json
url(r'^pub/(?P<pk>\d+)$',views.Pub.as_view({'get':'retrieve','put':'update','delete':'destroy'})), #获取一条
第三种(自动生成路由,必须继承ModelViewSet)
from django.conf.urls import url,include
SimpleRouter 自动生成两条路由
from rest_framework.routers import SimpleRouter,DefaultRouter #路由控制 router = SimpleRouter()
router.register('pub',views.Pub) urlpatterns = [
url(r'^admin/', admin.site.urls),
#其他路由 url(r'',include(router.urls)),]
DefaultRouter自动生成四条路由
from rest_framework.routers import SimpleRouter,DefaultRouter #路由控制 router = DefaultRouter()
router.register('pub',views.Pub) urlpatterns = [
url(r'^admin/', admin.site.urls),
#其他路由
url(r'',include(router.urls)),]
| 解析器(一般不需要动,项目最开始全局配置一下就可以了) |
作用:控制视图类能够解析前端传过来的格式是什么样的 (默认配置三种都有) 有application/json,x-www-form-urlencoded,form-data等格式
全局使用:在settings中配置:
REST_FRAMEWORK = {
"DEFAULT_PARSER_CLASSES":[
'rest_framework.parsers.JSONParser',]
}
局部使用:
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser
#json字典 urlencoded form-data 文件
在视图类中
parser_classes=[JSONParser,]
源码流程
当调用request.data的时候去执行解析方法

-->根据传过来的编码方式选择一个解析器对象

--->调用解析器对象的parser方法完成解析

在调用request.data时,才进行解析,由此入手
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
查看self._load_data_and_files()方法---->self._data, self._files = self._parse() def _parse(self):
#用户请求头里content_type的值
media_type = self.content_type #self.parsers 就是用户配置的parser_classes = [FileUploadParser,FormParser ]
#self里就有content_type,传入此函数
parser = self.negotiator.select_parser(self, self.parsers)
查看self.negotiator.select_parser(self, self.parsers)
def select_parser(self, request, parsers):
#同过media_type和request.content_type比较,来返回解析器,然后调用解析器的解析方法
#每个解析器都有media_type = 'multipart/form-data'属性
for parser in parsers:
if media_type_matches(parser.media_type, request.content_type):
return parser
return None
最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)
源码注释
Request实例化,parsers=self.get_parsers()
Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
get_parsers方法,循环实例化出self.parser_classes中类对象
def get_parsers(self):
return [parser() for parser in self.parser_classes]
self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,找不到,会到getattr方法
def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr) try:
#调用self.user_settings方法,返回一个字典,字典再取attr属性
val = self.user_settings[attr]
except KeyError:
# Fall back to defaults
val = self.defaults[attr] # Coerce import strings into classes
if attr in self.import_strings:
val = perform_import(val, attr) # Cache the result
self._cached_attrs.add(attr)
setattr(self, attr, val)
return val
user_settings方法 ,通过反射去setting配置文件里找REST_FRAMEWORK属性,找不到,返回空字典
@property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings
源码注释2
| 响应器 |
解析成字符串 还是一个浏览器页面
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer #解析成字符串 还是浏览器样式的
# 不用动,就用全局配置即可默认配置中两个都有
全局使用
在settings中配置 settings默认配置中两个都有
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser',
],
# 响应器 默认配置两个都由 这个是全局使用
# 'DEFAULT_PARSER_CLASSES':[ 'rest_framework.renderers.JSONRenderer',
# 'rest_framework.renderers.BrowsableAPIRenderer',]
}
局部使用
在试图类中配置
renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
| 版本控制 |
作用用于控制版本 视图中 版本问题需要接受版本传过来的参数 注意是单个没有复数
内置版本控制
from rest_framework.versioning import QueryParameterVersioning,AcceptHeaderVersioning,NamespaceVersioning,URLPathVersioning #基于url的get传参方式:QueryParameterVersioning------>如:/users?version=v1
#基于url的正则方式:URLPathVersioning------>/v1/users/
#基于 accept 请求头方式:AcceptHeaderVersioning------>Accept: application/json; version=1.0
#基于主机名方法:HostNameVersioning------>v1.example.com
#基于django路由系统的namespace:NamespaceVersioning------>example.com/v1/users/
局部使用
#在CBV类中加入
versioning_class = URLPathVersioning
url中需要写
url(r'(?P<version>[v1|v2])/register/$',views.Register.as_view()),
url(r'(?P<version>[v1|v2])/register\.(?P<format>\w+)$',views.Register.as_view()),
url(r'(?P<version>[v1|v2])/register/(?P<pk>\d+)$',views.Register.as_view()),
写访问路由的的时候要写上版本

全局使用
在settings中配置
REST_FRAMEWORK = {
"DEFAULT_PARSER_CLASSES":[
'rest_framework.parsers.JSONParser',
],
'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1', # 默认版本(从request对象里取不到,显示的默认值)
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本
'VERSION_PARAM': 'version', # URL中获取值的key
}
路由不要写
url(r'register/$',views.Register.as_view()),
但是访问路由的时候需要写上版本

在试图类中就可以通过,request.vesrsion取出当前访问哪个版本,相应的去执行相应版本的代码
示例
基于正则的方式
from django.conf.urls import url, include
from web.views import TestView urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'),
] url
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning class TestView(APIView):
versioning_class = URLPathVersioning def get(self, request, *args, **kwargs):
# 获取版本
print(request.version)
# 获取版本管理的类
print(request.versioning_scheme) # 反向生成URL
reverse_url = request.versioning_scheme.reverse('test', request=request)
print(reverse_url) return Response('GET请求,响应内容') views.py
View.py
# 基于django内置,反向生成url
from django.urls import reverse
url2=reverse(viewname='ttt',kwargs={'version':'v2'})
print(url2)
源码分析
#执行determine_version,返回两个值,放到request对象里
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme def determine_version(self, request, *args, **kwargs):
#当配置上版本类之后,就会实例化
if self.versioning_class is None:
return (None, None)
scheme = self.versioning_class()
return (scheme.determine_version(request, *args, **kwargs), scheme)
| 分页 |
常规分页 查看第n页 每页显示多少条
#分页 #常规分页 偏移分页 cursor游标分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class PublishView(APIView):
versioning_class = URLPathVersioning
parser_classes = [JSONRenderer,] #解析器 def get(self,request,*args,**kwargs):
#第一种方法,普通分页
'''
查询出所有数据
实例化产生一个普通分页对象
每页显示多少条
查询指定查询那一页的key值
'''
ret= models.Publish.objects.all()
page = PageNumberPagination()
page.page_size = 3 #每页显示多少条
page.page_query_param = 'page' #按照page名词显示那一页 # 前端控制每页显示多少条的查看key值必然要size=9,表示一页显示9条
page.page_size_query_param = 'size'
#控制每页最大显示多少,size如果传100,最多也是显示10
page.max_page_size = 10
ret_page = page.paginate_queryset(ret,request,self)
#序列化
pub_ser = PublishSerlizers(ret_page,many=True)
#去settings中配置每页显示多少条 这个是全局配置的话 局部配置全局可以不配置 return Response(pub_ser.data)
settings中配置
REST_FRAMEWORK = {
# 每页显示两条
'PAGE_SIZE':2
}
路由
url(r'^(?P<version>[v1|v2]+)/publish/',views.PublishView.as_view())
serializer
from rest_framework.serializers import ModelSerializer
from app01 import models
class PublishSerlizers(ModelSerializer):
class Meta:
model = models.Publish
fields = '__all__'
偏移分页 在第n个位置向前向后查询第n个位置
#分页 #常规分页 偏移分页 cursor游标分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class PublishView(APIView):
versioning_class = URLPathVersioning
parser_classes = [JSONRenderer,] #解析器 def get(self,request,*args,**kwargs): #偏移分页
ret = models.Publish.objects.all()
#实例化产生一个偏移分页对象
page= LimitOffsetPagination()
# 四个参数:
# 从标杆位置往后取几个,默认取3个,可以指定
page.default_limit = 3
# 每条取得条数
page.limit_query_param ='limit'
# 标杆值,现象偏移到那个位置,如果offset=6, 表示当前在第6条位置上,往后取
page.offset_query_param = 'offset'
# 最大取10条
page.max_limit = 10 ret_page = page.paginate_queryset(ret,request,self)
#序列化
pub_ser= PublishSerlizers(ret_page,many=True)
#取settings中配置每页显示多少条
return page.get_paginated_response(pub_ser.data)
cursor游标分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
class PublishView(APIView):
versioning_class = URLPathVersioning
parser_classes=[JSONParser,] def get(self, request, *args, **kwargs):
ret = models.Publish.objects.all()
# 实例化产生一个偏移分页对象
page = CursorPagination()
#三个参数:
#每页显示的大小
page.page_size=3
#查询的key值
page.cursor_query_param='cursor'
# 按什么排序
page.ordering='id' ret_page = page.paginate_queryset(ret, request, self)
# 序列化
pub_ser = serializer.PublishSerializers(ret_page, many=True)
# 去setting中配置每页显示多少条
return page.get_paginated_response(pub_ser.data)
DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)的更多相关文章
- drf 解析器,响应器,路由控制
解析器 作用: 根据请求头 content-type 选择对应的解析器对请求体内容进行处理. 有application/json,x-www-form-urlencoded,form-data等格式 ...
- Django框架深入了解_04(DRF之url控制、解析器、响应器、版本控制、分页)
一.url控制 基本路由写法:最常用 from django.conf.urls import url from django.contrib import admin from app01 impo ...
- DRF的解析器和渲染器
解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentTy ...
- DRF 的解析器和渲染器
一.解析器 解析器作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentT ...
- 【DRF解析器和渲染器】
目录 解析器 Django中的解析器 DRF中的解析器 DRF中的渲染器 @ *** 解析器 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己想要的数据类型的过程. 本质就是对请求体中的 ...
- Django REST framework解析器和渲染器
解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentTy ...
- 打造属于前端的Uri解析器
今天和大家一起讨论一下如何打造一个属于前端的url参数解析器.如果你是一个Web开发工程师,如果你了解过后端开发语言,譬如:PHP,Java等,那么你对下面的代码应该不会陌生: $kw = $_GET ...
- 高性能Java解析器实现过程详解
如果你没有指定数据或语言标准的或开源的Java解析器, 可能经常要用Java实现你自己的数据或语言解析器.或者,可能有很多解析器可选,但是要么太慢,要么太耗内存,或者没有你需要的特定功能.或者开源解析 ...
- Django REST framework基础:解析器和渲染器
解析器 解析器的作用 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据.本质就是对请求体中的数据进行解析. 在了解解析器之前,我们要先知道Accept以及ContentTy ...
随机推荐
- CSS简单选择器的学习笔记
我们知道通过CSS定义页面样式的时候要用到各种各样的选择器,正确的使用选择器是我们能够正确使用CSS做页面样式的基础.下面是我学习选择器的一个简易笔记,举一些简单的例子. 为了方便展示,我选择在内部的 ...
- vmware中桥接模式和NAT的区别
桥接模式 在桥接模式下,VMWare虚拟出来的操作系统就像是局域网中的一台独立的主机(主机和虚拟机处于对等地 位),它可以访问网内任何一台机器.在桥接模式下,我们往往需要为虚拟主机配置IP地址.子网掩 ...
- 前端工程师需要掌握的 Babel 知识
在前端圈子里,对于 Babel,大家肯定都比较熟悉了.如果哪天少了它,对于前端工程师来说肯定是个噩梦.Babel 的工作原理是怎样的可能了解的人就不太多了.本文将主要介绍 Babel 的工作原理以及怎 ...
- @Value和@PropertySource实现*.properties配置文件读取过程和实现原理
@Value和@PropertySource实现*.properties 配置文件读取过程和实现原理 1 配置使用步骤 (1)右击resource目录添加*.prooerties配置文件
- spring事务之事务传播机制和隔离级别
Spring事务传播行为 运用Spring事务,必须要深入理解它的传播机制,否则会遇到各种意想不到的坑,Spring定义了七种传播行为. public interface TransactionDef ...
- linux下查看tomcat的日志
工作期间有碰到服务器日志相关的,需要看tomcat运行日志,简单搜了下,摘为随笔,以供参考 一种是利用docker查看 1.使用dockerdocker logs -f -t --since=&quo ...
- Centos7 yum安装mysql(完整版)
1.下载mysql 地址:https://dev.mysql.com/downloads/repo/yum/.选择对应版本下载.
- Qt 单元测试
使用Qtcreator 自带的单元测试工具框架QTestlib进行测试. 一.创建一个单元测试程序 new project->other project ->Qt unit test ...
- ansible简单入门
1,结构框架 Ansible 使用的是无代理体系结构,这种体系结构可以通过防止节点轮询控制机器来减少网络开销.Ansible 提供的结果框架如下所示: Ansible :运行在中央计算机上: Conn ...
- OriginPro 9.1 科研图标绘制入门
OriginPro 9.1 科研图标绘制入门 目的:1.介绍如何不用编程画出复杂多样的图表2.介绍OriginLab 常用功能3.科研报告时,有效绘图,省却时间 科研发展需求.反映专业形象.满足公司要 ...