I created an AliasedOrderingFilter that should fit this need pretty well. It extends the ordering_fields attribute to allow tuples for fields as well as strings. For example, you can set orderings_views fields of the form:
ordering_fields = (('alias1', 'field1'),('alias2', 'field2'), 'field3')
Using this class in a query with ordering=alias1,-alias2,field3will result in:
qs.order_by('field1', '-field2', 'field3)
Grade:
class AliasedOrderingFilter(OrderingFilter):
''' this allows us to "alias" fields on our model to ensure consistency at the API level
We do so by allowing the ordering_fields attribute to accept a list of tuples.
You can mix and match, i.e.:
ordering_fields = (('alias1', 'field1'), 'field2', ('alias2', 'field2')) '''
def remove_invalid_fields(self, queryset, fields, view):
valid_fields = getattr(view, 'ordering_fields', self.ordering_fields)
if valid_fields is None or valid_fields == '__all__':
return super(AliasedOrderingFilter, self).remove_invalid_fields(queryset, fields, view)
aliased_fields = {}
for field in valid_fields:
if isinstance(field, basestring):
aliased_fields[field] = field
else:
aliased_fields[field[0]] = field[1]
ordering = []
for raw_field in fields:
invert = raw_field[0] == '-'
field = raw_field.lstrip('-')
if field in aliased_fields:
if invert:
ordering.append('-{}'.format(aliased_fields[field]))
else:
ordering.append(aliased_fields[field])
return ordering
source
share