Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use OrderingFilter without exposing the names of the fields in the database

I have a model that uses the OrderingFilter Backend. Right now only ordering by field id is allowed.

I want to give the option for ordering by other fields too but without having to expose the field names in my database. Is there a way to do that?

like image 387
LetsPlayYahtzee Avatar asked Nov 13 '15 11:11

LetsPlayYahtzee


Video Answer


1 Answers

I created an AliasedOrderingFilter that should fit this need rather well. It extends the ordering_fields attribute to allow tuples for fields as well as strings. For example you could set the views ordering_fields to:

ordering_fields = (('alias1', 'field1'),('alias2', 'field2'), 'field3')

Using this class in a request with ordering=alias1,-alias2,field3 will result in:

qs.order_by('field1', '-field2', 'field3)

The class:

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
like image 192
brocksamson Avatar answered Jan 04 '23 11:01

brocksamson