day 092 DRF -- 分页 | 解析器 | 渲染器
主要内容:
- 1.分页
- 2.解析器
- 3. 渲染器
1.分页
1.1 概述
(1)为什么使用分页
- 我们数据表中可能会有成千上万条数据,当我们访问某张表的所有数据时,我们不太可能需要一次把所有的数据都展示出来,因为数据量很大,对服务端的内存压力比较大还有就是网络传输过程中耗时也会比较大。
- 通常我们会希望一部分一部分去请求数据,也就是我们常说的一页一页获取数据并展示出来。
(2)分页器的使用
- rest framework中提供了三种分页模式:
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
- 全局配置
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 100 }
- 局部配置
from DRF.pagination import MyPageNumber, MyLimitPager, MyCursor class PublisherListView(ListCreateAPIView): queryset = models.Publisher.objects.all() serializer_class = PublisherModelSerializer pagination_class = MyCursor #注意不是列表,只能有一种分页模式
1.2 DRF内置分页器
(1)PageNumberPagination -- > 按页码数分页,第n页,每页显示m条数据 例如:http://127.0.0.1:8000/publisher/?page=2&size=1
- 分页器
class MyPageNumber(PageNumberPagination): page_size = 2 # 每页显示多少条 page_size_query_param = 'size' # URL中每页显示条数的参数 page_query_param = 'page' # URL中页码的参数 max_page_size = None # 最大页码数限制
- 视图
rom DRF.pagination import MyPageNumber, MyLimitPager, MyCursor class PublisherListView(ListCreateAPIView): queryset = models.Publisher.objects.all() serializer_class = PublisherModelSerializer pagination_class = MyPageNumber def get_queryset(self): if self.request.version == 'v1': return models.Publisher.objects.all().filter(id__gt=2) else: return self.queryset.all()
(2)LimitOffsetPagination -- > 分页,在n位置,向后查看m条数据 例如:http://127.0.0.1:8000/publisher/?offset=2&llmit=1
- 分页
# offset分页 class MyLimitOffset(LimitOffsetPagination): default_limit = 1 limit_query_param = 'limit' offset_query_param = 'offset' max_limit = 999
- 视图
from DRF.pagination import MyPageNumber, MyLimitPager, MyCursor class PublisherListView(ListCreateAPIView): queryset = models.Publisher.objects.all() serializer_class = PublisherModelSerializer pagination_class = MyLimitPager def get_queryset(self): if self.request.version == 'v1': return models.Publisher.objects.all().filter(id__gt=2) else: return self.queryset.all()
(2)CursorPagination -- > 加密分页,把上一页和下一页的id值记住
- 分页器
# 加密分页 class MyCursorPagination(CursorPagination): cursor_query_param = 'cursor' page_size = 1 ordering = '-id' # 重写要排序的字段
- 视图
from DRF.pagination import MyPageNumber, MyLimitPager, MyCursor class PublisherListView(ListCreateAPIView): queryset = models.Publisher.objects.all() serializer_class = PublisherModelSerializer pagination_class = MyCursor def get_queryset(self): if self.request.version == 'v1': return models.Publisher.objects.all().filter(id__gt=2) else: return self.queryset.all()
注; CursorPagination -- 用户让别人看不到具体的页码,页码都是随机字符串
-- http://127.0.0.1:8000/publisher/?cursor=cj0xJnA9NQ%3D%3D ---
注:
2. 解析器
2.1 解析器的作用:
解析器的作用就是 服务端接收客户端传过来的数据,把数据解析成自己可以处理的数据。本质就是对请求体中的数据进行解析。
2.2 Accept & ContentType请求头
- Accept是告诉对方我能解析什么样的数据,通常也可以表示我想要什么样的数据。
- ContentType是告诉对方我给你的是什么样的数据类型。
注: 解析器工作原理的就是拿到请求的ContentType来判断前端给我的数据类型是什么,然后我们在后端使用相应的解析器去解析数据
2.3 Django中的数据解析
视图中我们通过request.POST来获取前端发来的请求数据
Django --> 得到请求体中 的数据
Django的视图中通过request.POST和request.FILES能够取到数据都是因为在这里把请求的数据解析,并赋值给request对象了。
2.4 DRF中的解析器
在DRF中获取请求提交的数据是通过访问request.data,更重要的是 DRF可以解析json格式的数据。
如果没有配置解析器,DRF会使用默认的解析器
注: 我们可以在单个视图或者全局的settings.py中配置要使用的解析器。
- 单个视图配置
class BookViewSet(ModelViewSet): queryset = models.Book.objects.all() serializer_class = BookModelSerializer parser_classes = [JSONParser, ]
- 全局配置
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', ) }
注意:当你的项目中只配置了 JSONParser 解析器时,你的项目现在就只能解析JSON格式的数据了,客户端如果使用浏览器提交,那么你将无法解析。
注意,在视图类中定义的配置项的优先级要高于全局配置中的配置项。
3. 渲染器
渲染器同解析器相反,它定义了框架按照content_type来返回不同的响应
DRF提供的渲染器有很多,默认是
'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ),
- 局部渲染
class PublisherViewSet(ModelViewSet): queryset = models.Publisher.objects.all() serializer_class = PublisherModelSerializer renderer_classes = [JSONRenderer, ]
- 全局渲染
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', ), }
注;在视图类中定义的配置项的优先级要高于全局配置中的配置项