折腾:
期间,现在需要去Django中自定义返回分页数据,以便于前后端搭配,实现返回需要的数据
所以,现在就是去想办法让返回的数据,在当传入:
scripts/?page=2&page_size=20
时,不是返回所有的数据,而只是返回第一页的20个的数据
所以去后台Django中,去改代码
后端代码原先是:
def list(self, request, *args, **kwargs):
"""
获取 script list,取 author=request.user。按历史记录 version 最新的一个script,
组成列表
"""
logger.info("ScriptViewSet list: request=%s", request)
filterAuthorList = []
reqUser = request.user
logger.info("reqUser=%s", reqUser)
if reqUser.is_superuser :
# is superuser, means get all script list, so not filter himself
filterAuthorList = []
else:
filterAuthorList = [reqUser]
# if pass in author_id or group_id, take precedence for filter author over request user
authorId = request.query_params.get('author_id', '')
groupId = request.query_params.get('group_id', '')
logger.info("authorId=%s, groupId=%s", authorId, groupId)
if authorId:
passInAuthor = User.objects.get(pk=authorId)
logger.info("passInAuthor=%s", passInAuthor)
if passInAuthor:
filterAuthorList = [passInAuthor]
elif groupId:
passInGroup = FunctionGroup.objects.get(pk=groupId)
logger.info("passInGroup=%s", passInGroup)
if passInGroup:
membersRelatedManager = passInGroup.members
logger.info("membersRelatedManager=%s", membersRelatedManager)
logger.info("type(membersRelatedManager)=%s", type(membersRelatedManager))
memberList = membersRelatedManager.all()
logger.info("memberList=%s", memberList)
filterAuthorList = memberList
logger.info("len=%d, filterAuthorList=%s", len(filterAuthorList), filterAuthorList)
userFilter = Q()
if filterAuthorList:
userFilter = Q(author__in=filterAuthorList)
logger.info("userFilter=%s", userFilter)
filterByUserScriptList = Script.objects.filter(userFilter)
logger.info("filterByUserScriptList=%s", filterByUserScriptList)
filterByUserScriptListLen = len(filterByUserScriptList)
logger.info("filterByUserScriptListLen=%s", filterByUserScriptListLen)
filter_condition = self.generateQueryFilterCondiction(request)
logger.info("filter_condition=%s", filter_condition)
result = []
historyIdList = []
for curScriptIdx, singleScript in enumerate(filterByUserScriptList):
logger.info("---[%d] singleScript=%s", curScriptIdx, singleScript)
scriptHistoryId = singleScript.history_id
logger.info("scriptHistoryId=%s", scriptHistoryId)
if scriptHistoryId not in historyIdList:
historyIdList.append(singleScript.history_id)
logger.info("historyIdList=%s", historyIdList)
historyIdListLen = len(historyIdList)
logger.info("historyIdListLen=%s", historyIdListLen)
for curHisotryIdIdx, eachHistoryId in enumerate(historyIdList):
logger.info("===[%d] eachHistoryId=%s", curHisotryIdIdx, eachHistoryId)
history = History.objects.get(pk=eachHistoryId)
logger.info("history=%s", history)
orderedScriptAllHistory = history.script_history.all().order_by('version')
logger.info("orderedScriptAllHistory=%s", orderedScriptAllHistory)
lastHistory = orderedScriptAllHistory.last()
logger.info("lastHistory=%s", lastHistory)
result.append(lastHistory.id)
logger.info("result=%s", result)
resultLen = len(result)
logger.info("resultLen=%s", resultLen)
queryset = Script.objects.filter(pk__in=result).filter(filter_condition).order_by('-created_at')
logger.info("queryset=%s", queryset)
page = self.paginate_queryset(queryset)
logger.info("page=%s", page)
serializer = ScriptSerializer(queryset, many=True)
logger.info("after ScriptSerializer serializer=%s", serializer)
serializedData = serializer.data
logger.info("serializedData=%s", serializedData)
respData = None
if page is not None:
respData = self.get_paginated_response(serializedData)
else:
respData = Response(serializedData)
logger.info("respData=%s", respData)
return respData现在要去改为支持传入的page和pagesize,返回对应page的值
经过调试发现返回的:
INFO|20180810 17:22:02|views:list:186|serializedData=[OrderedDict([('id', 'cb54d47d-6e9c-4ec2-8666-eb97df30e654'), ('place', 'cort'), ('title', 'play body'), ('topic', 'Shopping'), ('second_level_topic', 'cake shop'), ('age_start', 3), ('version', 1), ('age_end', 5), ('author', 'Maggie'), ('joinedScriptGroup', {'groupId': 5, 'groupName': 'maggie剧本组'}), ('publish_status', '未发布'), ('edit_status', '未提交'), ('review', None), ('dialog_count', 6), ('created_at', '2018-08-10 14:42:01'), ('updated_at',
...就是一个数组,然后调用了:self.get_paginated_response
所以要去搞清楚:get_paginated_response
Django get_paginated_response
现在需要实现:
返回的数据中包含:
{
"totalCount": 519,
"currentPageCount": 20,
"currentPageNumber": 4,
"maxPageNumber": 26,
"next": "
https://api.example.org/accounts/?page=5
",
"previous": "
https://api.example.org/accounts/?page=3
",
"results": [
{},
{},
{}
]
}而现有的pagination的class是:
/apps/core/pagination.py
from rest_framework.pagination import PageNumberPagination class StandardResultsSetPagination(PageNumberPagination): page_size = 20 page_size_query_param = 'page_size' max_page_size = 1000
需要去改造
且只返回当前页的数据
想要参考代码去自定义,但是需要获取当前page的值
搜到paginator去参考代码:
page = request.query_params.get('page', 1)
page_size = request.query_params.get('page_size', 20)
p = Paginator(file_list, page_size)
count = p.count
current_page = p.page(page)
if current_page.has_next():
next = api_url + str(current_page.next_page_number())
else:
next = None
if current_page.has_previous():
previous = api_url + str(current_page.previous_page_number())
else:
previous = None
current_page_object = current_page.object_list
format_current_page_object = []
for j in current_page_object:
item = {}
item['id'] = j[0]
item['name'] = j[1]
format_current_page_object.append(item)
return Response({
"count": count,
"next": next,
"previous": previous,
"results": format_current_page_object
}, status=status.HTTP_200_OK)去找找如何写代码,获取current的page
django pagination get current page number
实在不行,就自己参考上面的自己去返回自己要的效果
【已解决】Django中获取当前配置的参数出错:AttributeError dict object has no attribute
然后想要通过:
/apps/core/pagination.py
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
import logging
logger = logging.getLogger('django')
class StandardResultsSetPagination(PageNumberPagination):
page_size = 20
page_size_query_param = 'page_size'
max_page_size = 1000
class CustomPagination(PageNumberPagination):
page_size = 20
page_size_query_param = 'page_size'
max_page_size = 1000
def get_paginated_response(self, data, curPageNum):
# respDict = {
# 'next': self.get_next_link(),
# 'previous': self.get_previous_link(),
# 'count': self.page.paginator.count,
# 'results': data
# }
logger.info("CustomPagination get_paginated_response: self=%s,data=%s,curPageNum=%s", self, data, curPageNum)
logger.info("type(self)=%s", type(self))
logger.info("type(data)=%s", type(data))
logger.info("self.page=%s", self.page)
logger.info("self.page.paginator=%s", self.page.paginator)
totalCount = self.page.paginator.count
logger.info("totalCount=%s", totalCount)
maxPageCount = self.page.paginator.num_pages
logger.info("maxPageCount=%s", maxPageCount)
curPage = self.page.paginator.page(curPageNum)
logger.info("curPage=%s", curPage)
logger.info("type(curPage)=%s", type(curPage))
curPageItemList = curPage.object_list
logger.info("curPageItemList=%s", curPageItemList)
currentPageCount = len(curPageItemList)
logger.info("currentPageCount=%s", currentPageCount)
nextPageUrl = self.get_next_link()
previousPageUrl = self.get_previous_link()
respDict = {
"totalCount": totalCount,
"maxPageCount": maxPageCount,
"currentPageNumber": curPageNum,
"currentPageCount": currentPageCount,
"next": nextPageUrl,
"previous": previousPageUrl,
"results": curPageItemList
}
return Response(respDict)
然后去调用:
apps/script/views.py
def list(self, request, *args, **kwargs): if paginatedQueryset is not None: # respData = self.get_paginated_response(serializedData) respData = self.get_paginated_response(serializedData, page)
结果提示出错:
File "/Users/crifan/dev/dev_root/company/xxx/projects/xxx/server/xxx/apps/script/views.py", line194, in list respData = self.get_paginated_response(serializedData, page) TypeError: get_paginated_response() takes 2 positional arguments but 3 were given
因为是继承的函数只有2个参数:
/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/rest_framework/generics.py
class GenericAPIView(views.APIView): def get_paginated_response(self, data): """ Return a paginated style `Response` object for the given output data. """ assert self.paginator is not None return self.paginator.get_paginated_response(data)
所以没法添加当前page的number
感觉只能放弃这条路。
django pagination return current page data
好像只能用Paginator只能去生成结果了?
django paginate current page data
好像自定义Pagenation的类中,可以获取request?
这样就可以获取page参数了。
去试试
然后发现了:
/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/rest_framework/generics.py
def paginate_queryset(self, queryset): """ Return a single page of results, or `None` if pagination is disabled. """ if self.paginator is None: return None return self.paginator.paginate_queryset(queryset, self.request, view=self)
即:paginate_queryset带了self.request-》可以获取到page参数的
不过还是之前的代码,发现在CustomPagination的get_paginated_response中,是可以获得当前page的:
INFO|20180810 21:51:34|pagination:get_paginated_response:28|type(self)=<class 'apps.core.pagination.CustomPagination'> INFO|20180810 21:51:34|pagination:get_paginated_response:29|type(data)=<class 'rest_framework.utils.serializer_helpers.ReturnList'> INFO|20180810 21:51:34|pagination:get_paginated_response:31|self.page=<Page 1 of 26> INFO|20180810 21:51:34|pagination:get_paginated_response:32|self.page.paginator=<django.core.paginator.Paginator object at 0x109bb1e48> INFO|20180810 21:51:34|pagination:get_paginated_response:35|totalCount=519 INFO|20180810 21:51:34|pagination:get_paginated_response:37|maxPageCount=26
那么后面就可以去只返回当前page的数据了。
而当前的page页数,可以通过:
“Attributes¶
Page.object_list¶
The list of objects on this page.
Page.number¶
The 1-based page number for this page.
Page.paginator¶
The associated Paginator object.”
的.number去获得
结果返回:
curPageItemList = curPage.object_list
logger.info("curPageItemList=%s", curPageItemList)
respDict = {
"totalCount": totalCount,
"maxPageCount": maxPageCount,
"currentPageNumber": curPageNum,
"currentPageCount": currentPageCount,
"next": nextPageUrl,
"previous": previousPageUrl,
"results": curPageItemList
}结果报错:
File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default o.__class__.__name__) TypeError: Object of type 'Script' is not JSON serializable
而改为:
curPageItemList = data
logger.info("curPageItemList=%s", curPageItemList)
currentPageCount = len(curPageItemList)
logger.info("currentPageCount=%s", currentPageCount)结果虽然没报错,又是回到了之前:返回了所有的数据

而如果想要在get_paginated_response中调用此处的
serializer = ScriptSerializer(queryset, many=True)
logger.info("after ScriptSerializer serializer=%s", serializer)
serializedData = serializer.data
logger.info("serializedData=%s", serializedData)去序列化-》则又会出现:
不知道实际上是哪个类的Serializer
而且本身很麻烦,干脆直接放弃get_paginated_response,自己用Paginator就好了
【总结】
目前把代码改为:
from django.core.paginator import Paginator
from rest_framework.response import Response
serializer = ScriptSerializer(queryset, many=True)
logger.info("after ScriptSerializer serializer=%s", serializer)
serializedData = serializer.data
logger.info("serializedData=%s", serializedData)
# respDict = None
# if paginatedQueryset is not None:
# respDict = self.get_paginated_response(serializedData)
# # respDict = self.get_paginated_response(serializedData, page)
# else:
# respDict = Response(serializedData)
# logger.info("respDict=%s", respDict)
# return respDict
curPaginator = Paginator(serializedData, page_size)
logger.info("curPaginator=%s", curPaginator)
totalCount = curPaginator.count
logger.info("totalCount=%s", totalCount)
maxPageCount = curPaginator.num_pages
logger.info("maxPageCount=%s", maxPageCount)
curPageNum = page
logger.info("curPageNum=%s", curPageNum)
curPage = curPaginator.page(curPageNum)
logger.info("curPage=%s", curPage)
logger.info("type(curPage)=%s", type(curPage))
curPageItemList = curPage.object_list
logger.info("curPageItemList=%s", curPageItemList)
currentPageCount = len(curPageItemList)
logger.info("currentPageCount=%s", currentPageCount)
# nextPageUrl = self.get_next_link()
# previousPageUrl = self.get_previous_link()
nextPageUrl = None
previousPageUrl = None
respDict = {
"totalCount": totalCount,
"maxPageCount": maxPageCount,
"pageSize": page_size,
"currentPageNumber": curPageNum,
"currentPageCount": currentPageCount,
"next": nextPageUrl,
"previous": previousPageUrl,
"results": curPageItemList
}
return Response(respDict, status=status.HTTP_200_OK)可以对于:
127.0.0.1 – – [10/Aug/2018 22:39:20] “GET /api/v1/scripts/?page=3&page_size=20 HTTP/1.1” 200 –
返回:
当前页,只有20个数据:

而不是所有的数据。
暂时凑合满足需求了。
转载请注明:在路上 » 【已解决】Django中如何自定义返回分页数据