6

Update Two

So unfortunately, @Reza Torkaman Ahmadi's idea didn't work out in the end. This is because our program has a filtering function that relies on get_queryset, and overriding the get_queryset method in our views was messing up that function.

So, my partner and I discussed it, and here's what he came up with.

class OrderbyFilter(filters.OrderingFilter): def get_ordering(self, request, queryset, view): """ Ordering is set by a comma delimited ?$orderby=... query parameter. Extends the OrderingFilter of the django rest framework to redefine ordering parameters to "asc" and "desc". """ params = request.query_params.get(self.ordering_param) if params: field_queries = [param.strip() for param in params.split(',')] fields = [] for field_query in field_queries: field_query = field_query.split() if len(field_query) <= 2: while "asc" in field_query: field_query.remove("asc") for i, field in enumerate(field_query): if field == "desc": field_query[i-1] = "-" + field_query[i-1] while "desc" in field_query: field_query.remove("desc") fields.append(field_query[0]) else: fields.append([param.strip() for param in params.split(',')]) ordering = self.remove_invalid_fields(queryset, fields, view, request) if ordering: return ordering return self.get_default_ordering(view)

Basically, this function over-rides Django REST's source code, specifically the get_ordering function in the OrderingFilter. What it does is, if 'asc' is in the query after the field, it removes it and treats it like normal (for normal ascension ordering)

Otherwise if 'desc' is there, it removed the 'desc', and applies a hyphen.

Update Answered. Applied @Reza Torkaman Ahmadi idea and it works great after modifying it to fit my needs. Thanks mate!

Currently, in Django API rest framework, if a user wants to see a list of something in ascending or descending order, they have to do the following:

'Datastream&order_by=-name' shows names in descending order 'Datastream&order_by=name' shows names in ascending order.

I want to make a custom query where typing in 'Datastream&order_by=asc name' will order the names by ascending order, and 'desc name' will do so in descending order.

I've looked at some of the source code for the REST framework, but I may be looking in the wrong area. Getting stumped on what I should do. Any ideas?

2
  • Just show how it's impemented now. Commented Dec 18, 2018 at 14:44
  • @SergeyPugach I don't understand what you mean. The reason I'm doing this is to match a certain API standard. using 'desc' is required Commented Dec 18, 2018 at 14:46

2 Answers 2

9

You can do it in your own way. like this:

class DatastreamViewSet(ModelViewSet):

    def get_queryset(self):
        queryset = super(DatastreamViewSet, self).get_queryset()

        order_by = self.request.query_params.get('order_by', '')
        if order_by:
            order_by_name = order_by.split(' ')[1]
            order_by_sign = order_by.split(' ')[0]
            order_by_sign = '' if order_by_sign == 'asc' else '-'
            queryset = queryset.order_by(order_by_sign + order_by_name)

        return queryset

this will look for query parameter order_by if is supplied then will split it by space, the first one will indicate to use + or - sign on order_by filter, and the second will be the name of it. so put it all together and create a text, pass it to order_by and your good to go.

for example:

?order_by=asc name

will be like this in django =>

return queryset.order_by('name')
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks mate. I applied this to my own program and modified it a bit to suit my needs (making sure it didn't interfere with my filtering function, etc.) Works great! I appreciate it man.
any time my friend :)
Nice! I've added an additional check to only allow it for certain field names. I'm not sure if I'll change the order by sign to make it more explicit though.
5

Django Rest Framework's standard way:

from rest_framework.filters import OrderingFilter

Then on your APIView or ViewSet

filter_backends = (OrderingFilter,)
ordering_fields = ['field_name']

query parameter is ordering and supports reverse ordering as well.

GET https://example.com/?ordering=-field_name

2 Comments

Should be [OrderingFilter] but this is a much better way to do this
@AustinnotfromBoston using a list or tuple will yield the same result here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.