From 13cb4716cd0db47dd31d3ea8339ceb2c51b3a8cb Mon Sep 17 00:00:00 2001 From: Amelia Cordwell Date: Wed, 26 Apr 2017 17:12:33 +1200 Subject: [PATCH] Pagination for Task List Number of tasks per page can be specified in the get request, but if not specified the endpoint will return all of them. Change-Id: I524249bf7e9f16feba8c9beaeb66267ec7da874e --- README.md | 13 ++++++++----- stacktask/api/v1/views.py | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1bf695f..d0c0f03 100644 --- a/README.md +++ b/README.md @@ -41,14 +41,17 @@ Creation and management of Tasks, Tokens, and Notifications is not modular and i Endpoints for the management of tasks, tokens, and notifications. Most of these are limited by roles, and are for admin use only. -* ../v1/task - GET +* ../v1/tasks - GET * A json containing all tasks. - * This will be updated to take parameters to refine the list. -* ../v1/task/ - GET + * Possible parameters are: + * filters (specified below) + * tasks_per_page, defaults to 25 + * page, page number to access (starts at 1) +* ../v1/tasks/ - GET * Get details for a specific task. -* ../v1/task/ - PUT +* ../v1/tasks/ - PUT * Update a task and retrigger pre_approve. -* ../v1/task/ - POST +* ../v1/tasks/ - POST * approve a task * ../v1/token - GET * A json containing all tokens. diff --git a/stacktask/api/v1/views.py b/stacktask/api/v1/views.py index d678f8e..53c2676 100644 --- a/stacktask/api/v1/views.py +++ b/stacktask/api/v1/views.py @@ -16,6 +16,7 @@ from logging import getLogger from django.conf import settings from django.utils import timezone +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from rest_framework.response import Response from rest_framework.views import APIView @@ -160,15 +161,40 @@ class TaskList(APIViewWithLogger): and their related actions. """ + page = request.GET.get('page', 1) + tasks_per_page = request.GET.get('tasks_per_page', None) + if 'admin' in request.keystone_user['roles']: if filters: tasks = Task.objects.filter(**filters).order_by("-created_on") else: tasks = Task.objects.all().order_by("-created_on") + + if tasks_per_page: + paginator = Paginator(tasks, tasks_per_page) + try: + tasks = paginator.page(page) + except EmptyPage: + return Response({'tasks': [], + 'pages': paginator.num_pages, + 'has_more': False, + 'has_prev': False}, status=200) + # NOTE(amelia): 'has_more'and 'has_prev' names are + # based on the horizon pagination table pagination names + except PageNotAnInteger: + return Response({'error': 'Page not an integer'}, + status=400) + task_list = [] for task in tasks: task_list.append(task._to_dict()) - return Response({'tasks': task_list}, status=200) + if tasks_per_page: + return Response({'tasks': task_list, + 'pages': paginator.num_pages, + 'has_more': tasks.has_next(), + 'has_prev': tasks.has_previous()}, status=200) + else: + return Response({'tasks': task_list}) else: if filters: # Ignore any filters with project_id in them @@ -183,10 +209,15 @@ class TaskList(APIViewWithLogger): tasks = Task.objects.filter( project_id__exact=request.keystone_user['project_id'] ).order_by("-created_on") + + paginator = Paginator(tasks, tasks_per_page) + tasks = paginator.page(page) + task_list = [] for task in tasks: task_list.append(task.to_dict()) - return Response({'tasks': task_list}, status=200) + return Response({'tasks': task_list, + 'pages': paginator.num_pages}, status=200) class TaskDetail(APIViewWithLogger):