Edgar Navasardyan
Edgar Navasardyan

Reputation: 4511

Django CursorPagination for ordering by several fields

I am using Django DRF's CursorPagination for lazy loading of my data, and currently my goal is to sort the data by more than one field.

This is how my code looks like now:

class EndlessPagination(CursorPagination):

    ordering_param = ''

    def set_ordering_param(self, request):
        self.ordering = request.query_params.get(self.ordering_param, None)

        if not self.ordering:
            raise ValueError('Url must contain a parameter named ' + 
                             self.ordering_param)
        if self.ordering.startswith("\"") or self.ordering.endswith("\""):
            raise ValueError('Ordering parameter should not include quotation marks'    

    def paginate_queryset(self, queryset, request, view=None):
        # This function is designed to set sorting param right in the URL
        self.set_ordering_param(request)
        return super(EndlessPagination, self).paginate_queryset(queryset, request, view)

This code works fine for urls like my_url/sms/270380?order_by=-timestamp, but what if I want to sort by several fields ?

Upvotes: 0

Views: 779

Answers (1)

JPG
JPG

Reputation: 88619

Use str.split() to split the url params

class EndlessPagination(CursorPagination):
    ordering_param = 'order_by'

    def set_ordering_param(self, request):
        ordering_param_list = request.query_params.get(self.ordering_param, None)

        self.ordering = ordering_param_list.split(',')

        # here, "self.ordering" will be a "list", so, you should update the validation logic
        """
        if not self.ordering:
            raise ValueError('Url must contain a parameter named ' +
                             self.ordering_param)
        if self.ordering.startswith("\"") or self.ordering.endswith("\""):
            raise ValueError('Ordering parameter should not include quotation marks'
        """

    def paginate_queryset(self, queryset, request, view=None):
        # This function is designed to set sorting param right in the URL
        self.set_ordering_param(request)
        return super(EndlessPagination, self).paginate_queryset(queryset, request, view)


Example URLs
1. my_url/sms/270380?order_by=-timestamp
2. my_url/sms/270380?order_by=-timestamp,name
3. my_url/sms/270380?order_by=-name,foo,-bar


UPDATE-1

First of all thanks to you for giving a chance to dig deep :)

As you said, me too didn't see comma seperated query_params in popular APIs. So, Change the url format to something like,

my_url/sms/270380??order_by=-name&order_by=foo&order_by=-bar
At this time, the request.query_params['order_by'] will be a list equal to ['-name','foo','-bar']. So, you don't want to use the split() function, hence your set_ordering_param() method become,

def set_ordering_param(self, request):
    self.ordering = request.query_params.get(self.ordering_param, None)
    #...... your other validations

Upvotes: 2

Related Questions