diff --git a/tailbone/api/master.py b/tailbone/api/master.py index fa42c316..209fb146 100644 --- a/tailbone/api/master.py +++ b/tailbone/api/master.py @@ -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 diff --git a/tailbone/api/users.py b/tailbone/api/users.py index fdf3872d..8ebfedf2 100644 --- a/tailbone/api/users.py +++ b/tailbone/api/users.py @@ -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() diff --git a/tailbone/templates/users/vue_index.mako b/tailbone/templates/users/vue_index.mako index b0703602..713ddb1a 100644 --- a/tailbone/templates/users/vue_index.mako +++ b/tailbone/templates/users/vue_index.mako @@ -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',