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
'rattail[db,bouncer]', # 0.5.0
'six', # 1.10.0
'sqlalchemy-filters', # 0.8.0
'transaction', # 1.2.0
'waitress', # 0.8.1
'WebHelpers2', # 2.0

View file

@ -26,7 +26,7 @@ Tailbone Web API - Master View
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.db import Session
@ -67,26 +67,51 @@ class APIMasterView(APIView):
def _collection_get(self):
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')
if sort:
# TODO: this is fragile, but what to do if bad params?
sortkey, sortdir = sort.split('|')
sortkey = getattr(cls, sortkey)
objects = objects.order_by(getattr(sortkey, sortdir)())
if sortdir != 'desc':
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?)
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)
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]
return {self.get_collection_key(): objects}
# these pagination values 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
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):
uuid = self.request.matchdict['uuid']