上篇吧分页漏掉了,这次补上,drf自带的分页不能满足我们的需求,需要我们自定义
如果不传page_size就不会触发分页,默然返回全部,也符合我的需求
from rest_framework.pagination import PageNumberPagination
from rest_framework.utils.urls import replace_query_param
from rest_framework.response import Response
from collections import OrderedDict
from util import codes
from util import message
# 定制分页
class ZkysPagination(PageNumberPagination):
"""
@description :最少提交page_size参数才会分页
---------
@param :
-------
@Returns :
-------
"""
# page_size = 10 # 每页显示多少个
page_size_query_param = 'page_size'
page_query_param = 'page' # 查询参数的名称。默认是’page‘
max_page_size = 100
ordered = ['id']
def get_num_pages_link(self):
url = self.request.build_absolute_uri()
num_pages = self.page.paginator.num_pages
return [replace_query_param(url, self.page_query_param, page) for page in range(1, num_pages + 1)]
def get_paginated_response(self, data):
return Response(OrderedDict([
('code', codes.normal_code),
('msg', message.normal_code),
('count', self.page.paginator.count),
('num_pages', self.page.paginator.num_pages), # 分页的总页码
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('pages', self.get_num_pages_link()), # 所有分页的链接
('results', data)
]))
url:
from django.urls import path
from zklf_wtg import views
urlpatterns = [
path('api/v1/blade_number/', views.BladeNumber.as_view({'get': 'list', 'post': '_create', 'put': "_update"}))
]
views:
list方法是重写的mixins.ListModelMixin,重写list方法可以让我们自己修改序列化的结果,以达到自定义的目的,drf提供的方法只是能满足很基本的需求,很多都是要我们自己重新定义的,也符合框架的理念。
views.APIView
# 只实现了身份验证,权限验证,限流等基本的验证方法,可以应用于一般的后端api设计
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
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
# Allow dependency injection of other settings to make testing easier.
settings = api_settings
schema = DefaultSchema()
viewsets.GenericViewSet :
可以看到GenericViewSet继承于APIView,在限流,权限,身份等验证的基础上添加了分页,过滤和序列化等高级功能。比较适合开发完善的api
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
"""
The GenericViewSet class does not provide any actions by default,
but does include the base set of generic view behavior, such as
the `get_object` and `get_queryset` methods.
"""
pass
class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
# You'll need to either set these attributes,
# or override `get_queryset()`/`get_serializer_class()`.
# If you are overriding a view method, it is important that you call
# `get_queryset()` instead of accessing the `queryset` property directly,
# as `queryset` will get evaluated only once, and those results are cached
# for all subsequent requests.
queryset = None
serializer_class = None
# If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
lookup_url_kwarg = None
# The filter backend classes to use for queryset filtering
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
# The style to use for queryset pagination.
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
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
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
# Allow dependency injection of other settings to make testing easier.
settings = api_settings
完整的api应用,仅供参考
class BladeNumber(mixins.ListModelMixin, viewsets.GenericViewSet):
"""
@description :
---------
@param :
-------
@Returns :
-------
"""
permission_classes = (MyPermission,) # 启动token验证
queryset = models.BladeNumberTableModel.objects.all()
# 序列化类
serializer_class = serializer.BladeNumberTableModelSerializer
# 过滤,排序
filter_backends = [DjangoFilterBackend, OrderingFilter]
filter_class = zkys_filter_backend.BladeNumberTableModelFilter # 过滤类
pagination_class = ZkysPagination # 分页器
# 指定排序的字段
ordering_fields = ("id", "c_time", "u_time")
# 默认排序字段
ordering = ["id"]
coreapi_fields_get = (
DocParam(name="analy_model_id", location='query', description='', required=False),
# DocParam(name="token", location='header', description='token'),
)
coreapi_fields_post = (
DocParam(name="task_id", location='body', description='', required=False),
DocParam(name="blade_one", location='body', description='', required=False),
DocParam(name="blade_two", location='body', description='', required=False),
DocParam(name="blade_three", location='body', description='', required=False),
)
coreapi_fields_put = (
DocParam(name="task_id", location='body', description='', required=False),
DocParam(name="blade_one", location='body', description='', required=False),
DocParam(name="blade_two", location='body', description='', required=False),
DocParam(name="blade_three", location='body', description='', required=False),
DocParam(name="is_delete", location='body', description='', required=False),
)
def list(self, request, *args, **kwargs):
context = {'code': codes.normal_code, 'msg': message.normal_code}
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
# serialized_data = serializer.data
# for _ in serialized_data:
# _["bucket_name"] = settings.MINIO_PANORAMA_BUCKET
context["results"] = serializer.data
return JsonResponse(context)
def _create(self, request):
"""
@description :新增数据
---------
@param :
-------
@Returns :
-------
"""
context = {'code': codes.normal_code, 'msg': message.normal_code}
verify_data = serializer.BladeNumberTableModelSerializer(data=request.data)
if verify_data.is_valid():
save = verify_data.save()
context["data"] = serializer.BladeNumberTableModelSerializer(instance=save).data
else:
context["code"] = codes.validate_param_code
context["msg"] = message.validate_param_code
context["data"] = verify_data.errors
return JsonResponse(context)
def _update(self, request):
"""
@description :更新数据
---------
@param :
-------
@Returns :
-------
"""
context = {'code': codes.normal_code, 'msg': message.normal_code}
task_id = request.data.get("task_id")
try:
model_obj = models.BladeNumberTableModel.objects.get(task_id=task_id)
except models.BladeNumberTableModel.DoesNotExist:
context["code"] = codes.id_notexist_code
context["msg"] = message.id_notexist_code
else:
verify_data = serializer.BladeNumberTableModelSerializer(instance=model_obj, data=request.data)
if verify_data.is_valid():
save = verify_data.save()
context["data"] = serializer.BladeNumberTableModelSerializer(instance=save).data
else:
context["code"] = codes.validate_param_code
context["msg"] = message.validate_param_code
context["data"] = verify_data.errors
return JsonResponse(context)