From 5c66eb5f4f2446adb47d7d1a1134734f06239808 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 20 Nov 2018 20:49:13 -0600 Subject: [PATCH] Refactor API collection_get to work with vue-tables-2 https://github.com/matfish2/vue-tables-2 --- tailbone/api/master.py | 94 +++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/tailbone/api/master.py b/tailbone/api/master.py index 6d3861d6..e8b5b938 100644 --- a/tailbone/api/master.py +++ b/tailbone/api/master.py @@ -26,6 +26,8 @@ Tailbone Web API - Master View from __future__ import unicode_literals, absolute_import +from rattail.config import parse_bool + from tailbone.api import APIView, api from tailbone.db import Session @@ -63,6 +65,52 @@ class APIMasterView(APIView): return cls.collection_key return '{}s'.format(cls.get_object_key()) + def make_sort_spec(self): + + # these params are based on 'vuetable-2' + # https://www.vuetable.com/guide/sorting.html#initial-sorting-order + if 'sort' in self.request.params: + sort = self.request.params['sort'] + sortkey, sortdir = sort.split('|') + if sortdir != 'desc': + sortdir = 'asc' + return [ + { + # 'model': self.model_class.__name__, + 'field': sortkey, + 'direction': sortdir, + }, + ] + + # these params are based on 'vue-tables-2' + # https://github.com/matfish2/vue-tables-2#server-side + if 'orderBy' in self.request.params and 'ascending' in self.request.params: + return [ + { + # 'model': self.model_class.__name__, + 'field': self.request.params['orderBy'], + 'direction': 'asc' if parse_bool(self.request.params['ascending']) else 'desc', + }, + ] + + def make_pagination_spec(self): + + # these params are based on 'vuetable-2' + # https://github.com/ratiw/vuetable-2-tutorial/wiki/prerequisite#sample-api-endpoint + if 'page' in self.request.params and 'per_page' in self.request.params: + page = self.request.params['page'] + per_page = self.request.params['per_page'] + if page.isdigit() and per_page.isdigit(): + return int(page), int(per_page) + + # these params are based on 'vue-tables-2' + # https://github.com/matfish2/vue-tables-2#server-side + if 'page' in self.request.params and 'limit' in self.request.params: + page = self.request.params['page'] + limit = self.request.params['limit'] + if page.isdigit() and limit.isdigit(): + return int(page), int(limit) + def _collection_get(self): from sqlalchemy_filters import apply_sort, apply_pagination @@ -70,33 +118,18 @@ class APIMasterView(APIView): query = self.Session.query(cls) context = {} - # TODO: should vuetable (etc.) be sending us valid sort_spec directly? - sort = self.request.params.get('sort') - if sort: - # TODO: this is fragile, but what to do if bad params? - sortkey, sortdir = sort.split('|') - if sortdir != 'desc': - sortdir = 'asc' - - sort_spec = [ - { - # 'model': self.model_class.__name__, - 'field': sortkey, - 'direction': sortdir, - }, - ] + # maybe sort query + sort_spec = self.make_sort_spec() + if sort_spec: query = apply_sort(query, sort_spec) - # NOTE: we only paginate results if sorting is in effect, otherwise - # record sequence is "non-determinant" (is that the word?) - page = self.request.params.get('page') - per_page = self.request.params.get('per_page') - if page.isdigit() and per_page.isdigit(): - page = int(page) - per_page = int(per_page) - query, pagination = apply_pagination(query, page_number=page, page_size=per_page) + # maybe paginate query + pagination_spec = self.make_pagination_spec() + if pagination_spec: + number, size = pagination_spec + query, pagination = apply_pagination(query, page_number=number, page_size=size) - # these pagination values are based on 'vuetable-2' + # these properties are based on 'vuetable-2' # https://www.vuetable.com/guide/pagination.html#how-the-pagination-component-works context['total'] = pagination.total_results context['per_page'] = pagination.page_size @@ -109,8 +142,21 @@ class APIMasterView(APIView): else: context['to'] = to + # these properties are based on 'vue-tables-2' + # https://github.com/matfish2/vue-tables-2#server-side + context['count'] = pagination.total_results + objects = [self.normalize(obj) for obj in query] + + # TODO: test this for ratbob! context[self.get_collection_key()] = objects + + # these properties are based on 'vue-tables-2' + # https://github.com/matfish2/vue-tables-2#server-side + context['data'] = objects + if 'count' not in context: + context['count'] = len(objects) + return context def _get(self):