06-Django REST framwork 板块(07-分页、08-视图、路由、09-渲染)

7. 分页

如果有1000万条数据,怎么分页?记录下结尾的位置,下次检索,直接跳到那个位置,然后取多少个

a. 分页,看第n页,每页显示n条数据;(基于PageNumberPagination,最常用)

  • 一:自己定义个类,继承自PageNumberPagination
  • 二:直接用PageNumberPagination
from rest_framework.pagination import PageNumberPagination

class MyPageNumberPagination(PageNumberPagination):

	page_size = 2    # 每页的数据条数
	page_size_query_param = 'size'		# 可以动态设置,这页展示多少条数据,但在max之下
	max_page_size = 5		# 每页最大显示数量
	page_query_param = 'page'	# 查询某一页的查询字段

class Pager1View(APIView):

	def get(self,request,*args,**kwargs):

		# 获取所有数据(要给一个排序的顺序,进行分页,不然会报警告)
		roles = models.Role.objects.all().order_by('-id')

		# 创建分页对象
		# pg = MyPageNumberPagination()
		pg = PageNumberPagination()

		# 在数据库中获取分页的数据
		pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)
			# queryset = 从数据库拿到的东西
			# request = request
			# view = 当前处理数据的视图,基本上都是self

		# 对数据进行序列化
		ser = PagerSerialiser(instance=pager_roles, many=True)

		#return Response(ser.data) # 直接返回对应数据
		
		# 返回分页生成器携带上下页链接的数据
		return pg.get_paginated_response(ser.data) 

如下所示,多包括了上下页链接,总共的数量:

{
	"count": 16,
	"next": "http://127.0.0.1:8000/api/v1/pager1/?page=3",
	"previous": "http://127.0.0.1:8000/api/v1/pager1/",
	"results": [
		{
			"id": 3,
			"user_type": 3,
			"username": "lucy",
			"password": "123"
		},
		{
			"id": 4,
			"user_type": 4,
			"username": "admin",
			"password": "admin"
		}
	]
}
		

b. 分页,在某个位置,向后查看n条数据;(基于LimitOffsetPagination)

from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination


class MyLimitOffsetPagination(LimitOffsetPagination):
	default_limit = 3  # 默认展示的数量
	limit_query_param = 'limit'   # 可查询的数据条数
	offset_query_param = 'offset'  # 基于第一条,向后偏移多少个(offset=0代表从第一个开始数)
	max_limit = 7  # 在最大显示多少条

# 视图处理定义是一样
class Pager1View(APIView):
	def get(self,request,*args,**kwargs):
		# 获取所有数据(要给一个排序的顺序,进行分页,不然会报警告)
		roles = models.Role.objects.all().order_by('-id')

		# 创建分页对象
		# pg = MyLimitOffsetPagination()
		pg = LimitOffsetPagination()

		# 在数据库中获取分页的数据
		pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

		# 对数据进行序列化
		ser = PagerSerialiser(instance=pager_roles, many=True)

		return Response(ser.data)
		# return pg.get_paginated_response(ser.data)

c. 加密分页,上一页和下一页(基于CursorPagination,对页码链接进行加密,避免恶意操作)。

from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

class MyCursorPagination(CursorPagination):
	cursor_query_param = 'cursor' # 游标页码值,进行加密后的页码字符串
	page_size = 2  # 每页显示的数据数量
	ordering = 'id'  # 排序方式('-id'表示按id倒序)
	page_size_query_param = 'size'   # 设置一个字段,通过url设置查询这页显示多少条数据
	max_page_size = None   # 每页最大显示数量

class Pager1View(APIView):

	def get(self,request,*args,**kwargs):

		# 获取所有数据(这个排序顺序在上边的ordering中指定了)
		roles = models.Role.objects.all()

		# 创建分页对象
		# pg = CursorPagination()
		pg = MyCursorPagination()

		# 在数据库中获取分页的数据
		pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

		# 对数据进行序列化
		ser = PagerSerialiser(instance=pager_roles, many=True)

		# return Response(ser.data)
		return pg.get_paginated_response(ser.data)

返回数据如下:

				
{
	"next": "http://127.0.0.1:8000/api/v1/pager3/?cursor=cD00",
	"previous": "http://127.0.0.1:8000/api/v1/pager3/?cursor=cj0xJnA9Mw%3D%3D",
	"results": [
		{
			"id": 3,
			"user_type": 3,
			"username": "lucy",
			"password": "123"
		},
		{
			"id": 4,
			"user_type": 4,
			"username": "admin",
			"password": "admin"
		}
	]
}

8. 视图

之前都是直接继承的APIview类,大部分东西都是自己写,当然还有其他的东西可以继承,
通过简单配置,实现分页、序列化等等功能。

a. 过去(Django的CBV模式)
	class Pager1View(View):
		pass
b. 现在 (rest framework的CBV模式)
	class Pager1View(APIView): # View
		pass
c. 无用(继承自APIView的类再次继承,基本不怎么用)(View --> APIView --> GenericAPIView)
from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.generics import GenericAPIView

class View1View(GenericAPIView): # APIView
	queryset = models.Role.objects.all()
	serializer_class = PagerSerialiser
	pagination_class = PageNumberPagination
	def get(self,request,*args,**kwargs):
		# 获取数据
		roles = self.get_queryset() # models.Role.objects.all()

		# [1, 1000,]     [1,10]
		pager_roles = self.paginate_queryset(roles)

		# 序列化
		ser = self.get_serializer(instance=pager_roles,many=True)

		return Response(ser.data)
d. 类:GenericViewSet(ViewSetMixin, generics.GenericAPIView):添加了不少功能,可以以在类中进行配置的方式,实现某些功能。
  • 路由:
url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list'})),
# 若继承自上边,则as_view方法中进行对应关系的设置,对于请求可以进行方法名的重定义
# key 代表请求过来的method名字, value为反射到的视图类中处理get请求的方法名。
  • 视图:
from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.viewsets import GenericViewSet

class View1View(GenericViewSet):
	queryset = models.Role.objects.all()   # 要查询的字段
	serializer_class = PagerSerialiser	# 序列化的类
	pagination_class = PageNumberPagination  # 执行分页的类

	def list(self, request, *args, **kwargs):
		# 获取数据
		roles = self.get_queryset()  # models.Role.objects.all()

		# 进行分页[1, 1000,]     [1,10]
		pager_roles = self.paginate_queryset(roles)

		# 序列化
		ser = self.get_serializer(instance=pager_roles, many=True)

		return Response(ser.data)
e. 最强大的类ModelViewSet,继承了6个类,增、删、改、查、局部更新、GenericViewSet
		(其中GenericViewSet上边还有父类,一个实现了as_view --> GenericAPIView --> APIView --> View)
class ModelViewSet(mixins.CreateModelMixin,
	   mixins.RetrieveModelMixin,
	   mixins.UpdateModelMixin,
	   mixins.DestroyModelMixin,
	   mixins.ListModelMixin,
	   GenericViewSet):
	"""
	A viewset that provides default `create()`, `retrieve()`, `update()`,
	`partial_update()`, `destroy()` and `list()` actions.
	以上这几个方法实现增加、获取(查)、更新(改)、局部更新、删除、列表操作。
	"""
	pass
  • 路由系统:
url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list','post':'create'})),
# 删改查都是基于对象ID来做的,所以这里要设置(?P<pk>\d+),使得视图函数能得到需要操作的对象的指针。
url(r'^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$', views.View1View.as_view({
																		'get': 'retrieve',
																		'delete':'destroy',
																		'put':'update',
																		'patch':'partial_update'})),
  • 视图:
from api.utils.serializsers.pager import PagerSerialiser
from rest_framework.viewsets import GenericViewSet,ModelViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin

# 在类中配置相应的字段
class View1View(ModelViewSet):
	queryset = models.Role.objects.all()   # 要查询的字段
	serializer_class = PagerSerialiser	# 序列化的类
	pagination_class = PageNumberPagination  # 执行分页的类
	
#**PS**: class View1View(CreateModelMixin,GenericViewSet):
#简单几行代码实现增删改查等基本功能

总结(使用继承类):

a. 增删改查 ModelViewSet
b. 增删 CreateModelMixin,DestroyModelMixin, GenericViewSet
c. 复杂逻辑 GenericViewSetAPIView


9. 路由

a.最普通的路由
url(r'^(?P<version>[v1|v2]+)/parser/$', views.ParserView.as_view()),
b. 当继承ViewSetMixin后,路由在as_view中有了方法映射关系
			url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list','post':'create'})),
c. 支持的路由格式(是渲染出来显示,还是纯json子字符串,不同的设置方式)
# http://127.0.0.1:8000/api/v1/v1/?format=json
url(r'^(?P<version>[v1|v2]+)/v1/$', views.View1View.as_view({'get': 'list','post':'create'})),
# http://127.0.0.1:8000/api/v1/v1.json
url(r'^(?P<version>[v1|v2]+)/v1\.(?P<format>\w+)$', views.View1View.as_view({'get': 'list','post':'create'})),

url(r'^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$', views.View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
url(r'^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)\.(?P<format>\w+)$', views.View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
d. 全自动路由(简单易用,单个情况最好自己写,包括所有基本的增删改查)
#在urls.py中
from api import views
from rest_framework import routers

# 会自动生成对应上边的四种路由形式	
router = routers.DefaultRouter()
router.register(r'xxxxx', views.View1View)   # 将视图函数注册进去    
router.register(r'rt', views.View1View)

# 在urlpatterns中配置
urlpatterns = [
	url(r'^(?P<version>[v1|v2]+)/', include(router.urls)),
]

10. 渲染

为了看json数据的页面展示效果,基本只需要在settings里边配置上就行。

from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer

class TestView(APIView):
	# renderer_classes = [JSONRenderer,BrowsableAPIRenderer]  # 平时只用这两个足够,设置加载配置文件中
	def get(self, request, *args, **kwargs):
		pass
		
		
REST_FRAMEWORK = {			
	"DEFAULT_RENDERER_CLASSES":[
		'rest_framework.renderers.JSONRenderer',
		'rest_framework.renderers.BrowsableAPIRenderer',
	]
}

当然也可以自己定制,根据类的继承查询界面的位置,找到原生界面修改界面代码,打自己公司的广告等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值