Use sqlalchemy-filters package for REST API collection_get

just sorting and pagination so far though, no actual filters yet
This commit is contained in:
Lance Edgar 2018-11-19 23:56:42 -06:00
parent 3e8d6a27f1
commit 46501b7caa
2 changed files with 34 additions and 8 deletions

View file

@ -88,6 +88,7 @@ requires = [
'pyramid_tm', # 0.3 'pyramid_tm', # 0.3
'rattail[db,bouncer]', # 0.5.0 'rattail[db,bouncer]', # 0.5.0
'six', # 1.10.0 'six', # 1.10.0
'sqlalchemy-filters', # 0.8.0
'transaction', # 1.2.0 'transaction', # 1.2.0
'waitress', # 0.8.1 'waitress', # 0.8.1
'WebHelpers2', # 2.0 'WebHelpers2', # 2.0

View file

@ -26,7 +26,7 @@ Tailbone Web API - Master View
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
from paginate_sqlalchemy import SqlalchemyOrmPage from sqlalchemy_filters import apply_sort, apply_pagination
from tailbone.api import APIView, api from tailbone.api import APIView, api
from tailbone.db import Session from tailbone.db import Session
@ -67,26 +67,51 @@ class APIMasterView(APIView):
def _collection_get(self): def _collection_get(self):
cls = self.get_model_class() cls = self.get_model_class()
objects = self.Session.query(cls) query = self.Session.query(cls)
context = {}
# TODO: should vuetable (etc.) be sending us valid sort_spec directly?
sort = self.request.params.get('sort') sort = self.request.params.get('sort')
if sort: if sort:
# TODO: this is fragile, but what to do if bad params? # TODO: this is fragile, but what to do if bad params?
sortkey, sortdir = sort.split('|') sortkey, sortdir = sort.split('|')
sortkey = getattr(cls, sortkey) if sortdir != 'desc':
objects = objects.order_by(getattr(sortkey, sortdir)()) sortdir = 'asc'
# NOTE: we only page results if sorting is in effect, otherwise sort_spec = [
{
# 'model': self.model_class.__name__,
'field': sortkey,
'direction': sortdir,
},
]
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?) # record sequence is "non-determinant" (is that the word?)
page = self.request.params.get('page') page = self.request.params.get('page')
per_page = self.request.params.get('per_page') per_page = self.request.params.get('per_page')
if page.isdigit() and per_page.isdigit(): if page.isdigit() and per_page.isdigit():
page = int(page) page = int(page)
per_page = int(per_page) per_page = int(per_page)
objects = SqlalchemyOrmPage(objects, items_per_page=per_page, page=page) query, pagination = apply_pagination(query, page_number=page, page_size=per_page)
objects = [self.normalize(obj) for obj in objects] # these pagination values are based on 'vuetable-2'
return {self.get_collection_key(): objects} # https://www.vuetable.com/guide/pagination.html#how-the-pagination-component-works
context['total'] = pagination.total_results
context['per_page'] = pagination.page_size
context['current_page'] = pagination.page_number
context['last_page'] = pagination.num_pages
context['from'] = pagination.page_size * (pagination.page_number - 1) + 1
to = pagination.page_size * (pagination.page_number - 1) + pagination.page_size
if to > pagination.total_results:
context['to'] = pagination.total_results
else:
context['to'] = to
objects = [self.normalize(obj) for obj in query]
context[self.get_collection_key()] = objects
return context
def _get(self): def _get(self):
uuid = self.request.matchdict['uuid'] uuid = self.request.matchdict['uuid']