一、解析器(parser)

  解析器在reqest.data取值的时候才执行。

  对请求的数据进行解析:是针对请求体进行解析的。表示服务器可以解析的数据格式的种类。

from rest_framework.parsers import JSONParser, FormParser, MultiPartParser, FileUploadParser
"""
默认得是 JSONParser FormParser MultiPartParser
"""
class BookView(APIView):
# authentication_classes = [TokenAuth, ]
parser_classes = [FormParser, JSONParser] def get(self, request):....

1、django的request类源码解析

(1)django中发送请求对比

#如果是urlencoding格式发送的数据,在POST里面有值
Content-Type: application/url-encoding.....
request.body
request.POST #如果是发送的json格式数据,在POST里面是没有值的,在body里面有值,可通过decode,然后loads取值
Content-Type: application/json.....
request.body
request.POST

(2)关于decode和encode

  浏览器发送过来是字节需要先解码 ---> decode 如:s=‘中文‘

  如果是在utf8的文件中,该字符串就是utf8编码,如果是在gb2312的文件中,则其编码为gb2312。这种情况下,要进行编码转换,都需要先用 decode方法将其转换成unicode编码,再使用encode方法将其转换成其他编码。通常,在没有指定特定的编码方式时,都是使用的系统默认编码创建的代码文件。 如下:

  s.decode(‘utf-8‘).encode(‘utf-8‘)

  decode():是解码 --->把字节变成字符串      encode()是编码---->把字符串变成字节

(3)查看django中WSGIRequest解析方法

# 1:导入django的类
from django.core.handlers.wsgi import WSGIRequest # 2:
class WSGIRequest(http.HttpRequest):
def _get_post(self):
if not hasattr(self, ‘_post‘):
self._load_post_and_files()
return self._post
# 3:self._load_post_and_files()从这里找到django解析的方法
def _load_post_and_files(self):
"""Populate self._post and self._files if the content-type is a form type"""
if self.method != ‘POST‘:
self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()
return
if self._read_started and not hasattr(self, ‘_body‘):
self._mark_post_parse_error()
return if self.content_type == ‘multipart/form-data‘:
if hasattr(self, ‘_body‘):
# Use already read data
data = BytesIO(self._body)
else:
data = self
try:
self._post, self._files = self.parse_file_upload(self.META, data)
except MultiPartParserError:
# An error occurred while parsing POST data. Since when
# formatting the error the request handler might access
# self.POST, set self._post and self._file to prevent
# attempts to parse POST data again.
# Mark that an error occurred. This allows self.__repr__ to
# be explicit about it instead of simply representing an
# empty POST
self._mark_post_parse_error()
raise
elif self.content_type == ‘application/x-www-form-urlencoded‘:
self._post, self._files = QueryDict(self.body, encoding=self._encoding), MultiValueDict()
else:
self._post, self._files = QueryDict(encoding=self._encoding), MultiValueDict()

  从if self.content_type == ‘multipart/form-data‘:和 self.content_type == ‘application/x-www-form-urlencoded‘: 可以知道django只解析urlencoded‘和form-data这两种类型。

  因此在django中传json数据默认是urlencoded解析到request中:body取到json数据时,取到的数据时字节,需要先decode解码,将字节变成字符串。

request.body.decode("utf8")
json.loads(request.body.decode("utf8"))

  为了传输json数据每次都要decode\loads,比较麻烦因此才有了解析器解决这个问题。

2、rest-framework的request类源码解析

  在rest-framework中 是以利用Request类进行数据解析。

1:找到apiview
class APIView(View):
# The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES # 解析器 2:找api_settings没有定义找默认
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES 3:.
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) 4:DEFAULTS DEFAULTS = {
# Base API policies # 自带的解析器
‘DEFAULT_PARSER_CLASSES‘: (
‘rest_framework.parsers.JSONParser‘,    # 仅处理请求头content-type为application/json的请求体
‘rest_framework.parsers.FormParser‘,    # 仅处理请求头content-type为application/x-www-form-urlencoded 的请求体
‘rest_framework.parsers.MultiPartParser‘  # 仅处理请求头content-type为multipart/form-data的请求体
),

  注意除了上面三种之外还有一个专门处理文件上传:

from rest_framework.parsers import FileUploadParser

3、局部视图parser

from rest_framework.parsers import JSONParser,FormParser
class PublishViewSet(generics.ListCreateAPIView):
parser_classes = [FormParser,JSONParser]
queryset = Publish.objects.all()
serializer_class = PublshSerializers
def post(self, request, *args, **kwargs):
print("request.data",request.data)
return self.create(request, *args, **kwargs)

4、全局视图parser

REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
"DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
"DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
"DEFAULT_THROTTLE_RATES":{
"visit_rate":"5/m",
},
"DEFAULT_PARSER_CLASSES":['rest_framework.parsers.FormParser',]
}

二、url路由控制

  因为我们使用的是视图集而不是视图,我们可以通过简单地将视图集注册到router类来为我们的API自动生成URL conf。

  同样,如果我们需要对API URL有更多的控制,我们可以直接使用常规的基于类的视图,并显式地编写URL conf。

  最后,我们将默认登录和注销视图包含在可浏览API中。这是可选的,但如果您的API需要身份验证,并且希望使用可浏览的API,那么这是有用的。

1、全自动路由示例

from django.contrib import admin

from django.urls import path, re_path, include
from rest_framework import routers
from app01 import views routers = routers.DefaultRouter() # 实例化
routers.register("authors", views.AuthorViewSet) # 注册某一个视图 urlpatterns = [
path('admin/', admin.site.urls),
...
# as_view参数指定什么请求走什么方法
# re_path(r'^authors/$', views.AuthorViewSet.as_view({"get": "list", "post": "create"}), name="author_list"),
# re_path(r'^authors/(?P<pk>\d+)/$', views.AuthorViewSet.as_view({
# 'get': 'retrieve',
# 'put': 'update',
# 'patch': 'partial_update',
# 'delete': 'destroy'
# }), name="author_detail"), # 改写如下:
re_path(r"", include(routers.urls)), re_path(r'^login/$', views.LoginView.as_view(), name="login"),
]

  视图的内容不需要任何变动即生效:

  

  

  

2、DRF路由组件使用

  路由传参写的特别多,但是框架将这些也已经封装好了。

  修改DRFDemo/urls.py文件如下所示:

from django.urls import path, include
from .views import BookView, BookEditView, BookModelViewSet
from rest_framework.routers import DefaultRouter router = DefaultRouter() # 路由实例化
# 第一个参数是路由匹配规则,这里的路由是分发下来的,因此可以不做设置;第二个参数是视图
router.register(r"", BookModelViewSet) urlpatterns = [
# path('list', BookView.as_view()), # 查看所有的图书
# 注意url中参数命名方式,2.0之前的写法:'retrieve/(?P<id>\d+)'
# 2.0之后的写法:<>内声明类型,冒号后面跟着关键字参数
# path('retrieve/<int:id>', BookEditView.as_view()) # 单条数据查看 # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
# path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"}))
] urlpatterns += router.urls # router.urls是自动生成带参数的路由

  但是需要自定制的时候还是需要我们自己用APIView写,当不需要那么多路由的时候,不要用这种路由注册,否则会对外暴露过多的接口,会存在风险。总之,一切按照业务需要去用。

三、分页组件(Pagination)

REST框架支持自定义分页风格,你可以修改每页显示数据集合的最大长度。

分页链接支持以下两种方式提供给用户:

  • 分页链接是作为响应内容提供给用户
  • 分页链接被包含在响应头中(Content-Range或者Link)

内建风格使用作为响应内容提供给用户。这种风格更容易被使用可浏览API的用户所接受。

  如果使用通用视图或者视图集合。系统会自动帮你进行分页。

  如果使用的是APIView,你就需要自己调用分页API,确保返回一个分页后的响应。可以将pagination_class设置为None关闭分页功能。

1、设置分页风格

  可以通过设置DEFAULT_PAGINATION_CLASS和PAGE_SIZE,设置全局变量。

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}

  需要同时设置pagination class和page size。 也可以在单个视图中设置pagination_class属性,但一般你需要使用统一的分页风格。

2、修改分页风格

  如果你需要修改分页风格 ,需要重写分页类,并设置你需要修改的属性。

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.serializer import *
from .utils import *
#分页
from rest_framework.pagination import PageNumberPagination class MyPageNumberPagination(PageNumberPagination):
# 默认每页显示的数据条数
page_size = 2
# 获取URL参数中设置的每页显示数据条数
page_size_query_param = 'size'
# 获取URL参数中传入的页码key
page_query_param = 'page'
# 最大支持的每页显示的数据条数(对这个进行限制127.0.0.1:8000/books/?page=1&size=100)
max_page_size = 3 class BookView(APIView):
# authentication_classes = [TokenAuth, ]
# parser_classes = [FormParser, JSONParser]
pagination_class = MyPageNumberPagination # 在视图中使用pagination_class属性调用该自定义类
def get(self, request):
book_list = Book.objects.all() # queryset # 实例化分页对象,获取数据库中的分页数据
pnp = MyPageNumberPagination()
books_page = pnp.paginate_queryset(book_list, request, self)
# 序列化对象
bs = BookModelSerializers(books_page, many=True, context={"request": request}) # 序列化结果
# return Response(bs.data)
return bs.get_paginated_response(bs.data) # 生成分页和数据 def post(self, request):.....

(1)设置max_page_size是限制直接在页面访问时最大的数据条数显示

  

  虽然总共有4条数据,页面访问get请求时?page=1&size=100但是依然只能拿到max_page_size限制拿到的3条。

3、根据页码分页——PageNumberPagination

  这个分页样式接受请求查询参数中的一个数字页面号。

GET https://api.example.org/accounts/?page=4

  响应对象:

HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?page=5",
"previous": "https://api.example.org/accounts/?page=3",
"results": [

]
}

  继承了APIView的视图,也可以设置pagination_class属性选择PageNumberPagination

class MyPageNumberPagination(PageNumberPagination):
# 默认每页显示的数据条数
page_size = 1 # 获取URL参数中设置的每页显示数据条数
page_size_query_param = 'size' # 获取URL参数中传入的页码key
page_query_param = 'page' # 最大支持的每页显示的数据条数(对这个进行限制127.0.0.1:8000/books/?page=1&size=100)
max_page_size = 3

  更多配置属性:

  • django_paginator_class  使用Django分页类。默认为django.core.paginator.Paginator,适用于大多数情况
  • page_size  用来显示每页显示对象的数量,如果设置了就重写PAGE_SIZE设置。
  • page_query_param  页面查询参数,一个字符串值,指示用于分页控件的查询参数的名称。
  • page_size_query_param  该参数允许客户端根据每个请求设置页面大小。一般默认设置为None.
  • max_page_size  只有设置了page_size_query_param参数,该参数才有意义,为客户端请求页面中能够显示的最大数量
  • last_page_strings  用于存储使用page_query_param参数请求过的值列表或元组,默认为(‘last’,)
  • template  用来在可浏览API中,渲染分页的模板(html)名字,可以重写分页样式,或者设置为None,禁用分页。默认为”rest_framework/pagination/numbers.html”。

4、根据位置和个数分页——LimitOffsetPagination

  这种分页样式与查找多个数据库记录时使用的语法类似。客户端包括一个”limit”和一个 “offset”查询参数。该限制表示返回的条目的最大数量,并且与page_size大小相同。偏移量表示查询的起始位置,与完整的未分页项的集合有关。

GET https://api.example.org/accounts/?limit=100&offset=400

HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/accounts/?limit=100&offset=500",
"previous": "https://api.example.org/accounts/?limit=100&offset=300",
"results": [

]
}

  这种也可以设置PAGE_SIZE,然后客户端就可以设置limit参数了。
  继承了GenericAPIView的子类,可以通过设置pagination_class属性为LimitOffsetPagination使用

class MyLimitOffsetPagination(LimitOffsetPagination):
# 默认每页显示的数据条数
default_limit = 1
# URL中传入的显示数据条数的参数
limit_query_param = 'limit'
# URL中传入的数据位置的参数
offset_query_param = 'offset'
# 最大每页显得条数
max_limit = None

(重写LimitOffsetPagination类)配置:

  • default_limit: 如果客户端没有提供,则默认使用与PAGE_SIZE值一样。
  • limit_query_param:表示限制查询参数的名字,默认为’limit’
  • offset_query_param:表示偏移参数的名字, 默认为’offset’
  • max_limit:允许页面中显示的最大数量,默认为None
  • template: 渲染分页结果的模板名,默认为”rest_framework/pagination/numbers.html”.

5、游标分页——CursorPagination

  基于游标的分页显示了一个不透明的“cursor”指示器,客户端可以使用它来浏览结果集。这种分页方式只允许用户向前或向后进行查询。并且不允许客户端导航到任意位置。

  基于游标的分页要求在结果集中有一个惟一的、不变的条目顺序。这个排序通常是记录上的一个创建时间戳,用来表示分页的顺序。

  基于游标的分页比其他方案更复杂。它还要求结果集给出一个固定的顺序,并且不允许客户端任意地对结果集进行索引,但是它确实提供了以下好处:

  • 提供一致的分页视图。当使用正确的指针分页时,即使在分页过程中其他客户端插入新项时,客户端也不会在分页时看到同一个项两次。
  • 支持使用非常大的数据集。大量数据集使用基于off-set的分页方式可能会变得低效或不可用。基于指针的分页模式有固定的时间属性,并且随着数据集的大小的增加而不会减慢。
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination

class MyCursorPagination(CursorPagination):
# URL传入的游标参数
cursor_query_param = 'cursor'
# 默认每页显示的数据条数
page_size = 2
# URL传入的每页显示条数的参数
page_size_query_param = 'page_size'
# 每页显示数据最大条数
max_page_size = 1000
# 根据ID从大到小排列
ordering = "id"

6、设置全局配置

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
# 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
'PAGE_SIZE': 100
}

  显示效果:

  

四、响应器(response)

五、渲染器

  规定页面显示的效果(无用)。

1、局部添加渲染器

  urls.py:

from django.conf.urls import url, include
from api.views import course urlpatterns = [
# path('admin/', admin.site.urls),
url(r'^api/course/$', course.CourseView.as_view()),
]

  api/views/course.py:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer class CourseView(APIView): # 渲染器
# renderer_classes = [JSONRenderer] # 表示只返回json格式
renderer_classes = [JSONRenderer, BrowsableAPIRenderer] # 数据嵌套在html中展示 def get(self, request, *args, **kwargs):
return Response('...')

  显示效果:

  

2、全局添加渲染器

  settings.py:

# 渲染器配置到全局
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer']
}

  显示效果同上。

rest-framework框架——解析器、ur控制、分页、响应器、渲染器、版本的更多相关文章

  1. rest-framework解析器,url控制,分页,响应器,渲染器,版本控制

    解析器 1.json解析器 发一个json格式的post请求.后台打印: request_data---> {'title': '北京折叠'} request.POST---> <Q ...

  2. Django_rest_framework_渲染器/解析器/路由控制/分页

    目录 渲染器 解析器 路由控制 分页 渲染器 简介 什么是渲染器 根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件. 渲染器的作用 序列化.友好的展示数据 渲染器配置 首先要在set ...

  3. rest-framework之响应器(渲染器)

    rest-framework之响应器(渲染器) 本文目录 一 作用 二 内置渲染器 三 局部使用 四 全局使用 五 自定义显示模版 回到目录 一 作用 根据 用户请求URL 或 用户可接受的类型,筛选 ...

  4. restful(3):认证、权限、频率 & 解析器、路由控制、分页、渲染器、版本

    models.py中: class UserInfo(models.Model): name = models.CharField(max_length=32) psw = models.CharFi ...

  5. 5 解析器、url路由控制、分页、渲染器和版本

    1 数据解析器 1 什么是解析器 相当于request 中content-type 对方传什么类型的数据,我接受什么样的数据:怎样解析 无论前面传的是什么数据,都可以解开 例如:django不能解析j ...

  6. Spring Framework框架解析(1)- 从图书馆示例来看xml文件的加载过程

    引言 这个系列是我阅读Spring源码后的一个总结,会从Spring Framework框架的整体结构进行分析,不会先入为主的讲解IOC或者AOP的原理,如果读者有使用Spring的经验再好不过.鉴于 ...

  7. rest-framework 响应器(渲染器)

    一 作用: 根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件. 用户请求URL:    http://127.0.0.1:8000/test/?format=json    http ...

  8. 29.渲染器Renderer

    什么是渲染器     渲染器就是将服务器生成的数据格式转为http请求的格式   渲染器触发及参数配置 在DRF配置参数中,可用的渲染器作为一个类的列表进行定义 但与解析器不同的是,渲染器的列表是有顺 ...

  9. ArcGIS Engine专题地图渲染器的实现(入门版)

    专题地图(Thematic Map)是着重表示一种或数种自然要素特征或社会经济现象的地图 专题地图的内容由两部分构成: 1.专题内容——图上突出表示的自然或社会经济现象及其有关特征 2.地理基础——用 ...

随机推荐

  1. 14、OpenCV Python 直线检测

    __author__ = "WSX" import cv2 as cv import numpy as np #-----------------霍夫变换------------- ...

  2. ArcGIS10.4破解

    arcgis 10.4破解方法 *注意!Desktop,Engine,Server必须为同一版本* Engine10.4破解失败,SDE10.4未进行破解 1.先安装License10.4 2.再安装 ...

  3. MYSQL 面试常见问题汇总

    转自: https://blog.csdn.net/u011010851/article/details/80074550 Q1:主键,外键,超键,候选键:主键    对表中数据进行唯一标识的数据列的 ...

  4. JavaScript的高级知识---词法分析

    JavaScript的高级知识---词法分析 词法分析 词法分析方法: js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤: 分析参数 再分析变量的声明 分析函数说明 函数在运行的瞬间, ...

  5. 老男孩python作业6-选课系统开发

    角色:学校.学员.课程.讲师要求:1. 创建北京.上海 2 所学校2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开3. 课程包含,周期,价格 ...

  6. Python web前端 07 函数及作用域

    Python web前端 07 函数及作用域 一.函数 1.有名函数和匿名函数 #函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块 #函数就是包裹在花括号里面的代码块,前面使用了关键字fun ...

  7. 小程序给scroll-view设置高度,使得它能适配各种尺寸的手机

    scroll-view占满整个屏幕,且scroll-view的滚动不影响到页面其他地方的滚动 在iphone6的尺寸下,scroll-view设置高度为1110rpx,就不会影响页面其他地方的滚动 但 ...

  8. 完美的js继承

    //完美的js继承 少了类管理器 Object.extend=function(){ var fnTest = /\b_super\b/; //继承父类 var _super = arguments[ ...

  9. Python入门(1)

    1.编程语言 机器语言:直接用计算机能听懂的二进制指令去编写程序,需要了解硬件的细节 汇编语言:用英文标签取代二进制指令去编写程序,同样需要了解硬件的细节 高级语言:直接用人类能理解的表达方式去编写程 ...

  10. sql server优化思路

    查询速度慢的原因很多,常见如下几种:    1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)    2.I/O吞吐量小,形成了瓶颈效应.    3.没有创建计算列导致查询不优化 ...