diff --git a/greenmine/base/api.py b/greenmine/base/api.py index d461642c..aebe8cd6 100644 --- a/greenmine/base/api.py +++ b/greenmine/base/api.py @@ -1,14 +1,16 @@ # -*- coding: utf-8 -*- -from rest_framework import ( - mixins, - viewsets -) +from rest_framework import viewsets +from .pagination import HeadersPaginationMixin, ConditionalPaginationMixin -class ModelCrudViewSet(viewsets.ModelViewSet): +class ModelCrudViewSet(HeadersPaginationMixin, + ConditionalPaginationMixin, + viewsets.ModelViewSet): pass -class ModelListViewSet(viewsets.ReadOnlyModelViewSet): +class ModelListViewSet(HeadersPaginationMixin, + ConditionalPaginationMixin, + viewsets.ReadOnlyModelViewSet): pass diff --git a/greenmine/base/middleware.py b/greenmine/base/middleware.py index a85f1d60..79ff7364 100644 --- a/greenmine/base/middleware.py +++ b/greenmine/base/middleware.py @@ -24,7 +24,8 @@ COORS_ALLOWED_METHODS = getattr(settings, 'COORS_ALLOWED_METHODS', ['POST', 'GET', 'OPTIONS', 'PUT', 'DELETE', 'PATCH']) COORS_ALLOWED_HEADERS = getattr(settings, 'COORS_ALLOWED_HEADERS', ['Content-Type', 'X-Requested-With', - 'X-Session-Token', 'Accept-Encoding']) + 'X-Session-Token', 'Accept-Encoding', + 'X-Disable-Pagination']) COORS_ALLOWED_CREDENTIALS = getattr(settings, 'COORS_ALLOWED_CREDENTIALS', True) diff --git a/greenmine/base/pagination.py b/greenmine/base/pagination.py new file mode 100644 index 00000000..13253cd9 --- /dev/null +++ b/greenmine/base/pagination.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +from rest_framework.templatetags.rest_framework import replace_query_param + + +class ConditionalPaginationMixin(object): + def get_paginate_by(self, *args, **kwargs): + if "HTTP_X_DISABLE_PAGINATION" in self.request.META: + return None + return super().get_paginate_by(*args, **kwargs) + + +class HeadersPaginationMixin(object): + def paginate_queryset(self, queryset, page_size=None): + page = super().paginate_queryset(queryset=queryset, page_size=page_size) + + if page is None: + return page + + self.headers["X-Pagination-Total"] = page.paginator.count + self.headers["X-Paginated"] = "true" + + if page.has_next(): + num = page.next_page_number() + url = self.request.build_absolute_uri() + url = replace_query_param(url, "page", num) + self.headers["X-Pagination-Next"] = url + + if page.has_previous(): + num = page.previous_page_number() + url = self.request.build_absolute_uri() + url = replace_query_param(url, "page", num) + self.headers["X-Pagination-Prev"] = url + + return page + + def get_pagination_serializer(self, page): + return self.get_serializer(page.object_list, many=True)