Add patterns for joining tables in API list methods

i.e. we needed to do an *outer* join on User.person since that can be null
This commit is contained in:
Lance Edgar 2018-11-27 02:21:38 -06:00
parent 93aa96a339
commit b7319fd152
3 changed files with 43 additions and 10 deletions

View file

@ -118,12 +118,39 @@ class APIMasterView(APIView):
"""
return self.sortcol(order_by)
def sortcol(self, field_name, model_name=None):
def sortcol(self, *args):
"""
Return a simple ``SortColumn`` object which denotes the field and
optionally, the model, to be used when sorting.
"""
return SortColumn(field_name, model_name)
if len(args) == 1:
return SortColumn(args[0])
elif len(args) == 2:
return SortColumn(args[1], args[0])
else:
raise ValueError("must pass 1 arg (field_name) or 2 args (model_name, field_name)")
def join_for_sort_spec(self, query, sort_spec):
"""
This should apply any joins needed on the given query, to accommodate
requested sorting as per ``sort_spec`` - which will be non-empty but
otherwise no claims are made regarding its contents.
Please override as necessary, but in all cases you should return a
query, either untouched or else with join(s) applied.
"""
model_name = sort_spec[0].get('model')
return self.join_for_sort_model(query, model_name)
def join_for_sort_model(self, query, model_name):
"""
This should apply any joins needed on the given query, to accommodate
requested sorting on a field associated with the given model.
Please override as necessary, but in all cases you should return a
query, either untouched or else with join(s) applied.
"""
return query
def make_pagination_spec(self):
@ -153,6 +180,7 @@ class APIMasterView(APIView):
# maybe sort query
sort_spec = self.make_sort_spec()
if sort_spec:
query = self.join_for_sort_spec(query, sort_spec)
query = apply_sort(query, sort_spec)
# maybe paginate query

View file

@ -43,16 +43,20 @@ class UserView(APIMasterView):
def normalize(self, user):
return {
'username': user.username,
'person_name': six.text_type(user.person or ''),
'person_display_name': (user.person.display_name or '') if user.person else '',
'active': user.active,
}
def interpret_sortcol(self, order_by):
if order_by == 'person_name':
return self.sortcol('display_name', 'Person')
if order_by == 'person_display_name':
return self.sortcol('Person', 'display_name')
return self.sortcol(order_by)
def join_for_sort_model(self, query, model_name):
if model_name == 'Person':
query = query.outerjoin(model.Person)
return query
@view(permission='users.list')
def collection_get(self):
return self._collection_get()

View file

@ -88,17 +88,18 @@ var app = new Vue({
data: {
columns: [
'username',
'person_name',
'person_display_name',
'active'
],
options: {
filterable: false,
headings: {
person_display_name: "Person"
},
sortable: [
'username',
'person_name',
'person_display_name',
'active'
// TODO: add sort for Person.display_name
// 'person'
],
orderBy: {
column: 'username',