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