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

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


pip install django-filter

In your view:

from rest_framework import viewsets, filtersfrom django_filters.filters import OrderingFilterfrom .models import MyListfrom .serializers import MyListSerializerclass MyFilter(django_filters.FilterSet):    surname = django_filters.CharFilter(name="model_field_name_2")    order_by_field = 'ordering'    ordering = OrderingFilter(        # fields(('model field name', 'parameter name'),)        fields=(            ('model_field_name_1', 'name'),            ('model_field_name_2', 'surname'),            ('model_field_name_3', 'email'),        )    )    class Meta:        model = MyList        fields = ['model_field_name_2',]class MyListViewSet(viewsets.ModelViewSet):    serializer_class = MyListSerializer    filter_backends = (filters.DjangoFilterBackend,)    filter_class = MyFilter        def get_queryset(self):        return MyList.objects.all()

And you could do something like this:

/my-list?ordering=name,surname,email/my-list?ordering=-email&surname=taylor

django-filter docs:https://django-filter.readthedocs.io/en/latest/ref/filters.html#orderingfilter

drf docs:http://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend


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


Yes you can do that by using the ordering_fields attribute in your view like:

class YourViewSet(viewsets.ModelViewSet):    serializer_class = yourSerializer    filter_backends = (filters.OrderingFilter,)    ordering_fields = ('field1', 'field2')

In ordering_fields you mention all the fields by which you want to allow ordering.

Here field1 and field2 need not be present in the serializer fields attribute and therefore they won't be in your API response.

Update:Your request url should be like:

http://example.com/api/users?ordering=field1

ordering is the query parameter. You need to set ordering with the field name with which you want to order your queryset.

you can learn more here