Reputation: 20820
Django has the Lower
function, but this only works with ASC
(ascending) ordered queries.
Example URL:
'/api/locations/?ordering=-number,name'
We were using the below pattern:
from django.db.models.functions import Lower
class OrderingQuerySetMixin(object):
def get_queryset(self):
queryset = self.queryset
ordering = self.request.query_params.get('ordering', None)
if ordering:
if ordering.startswith('-'):
queryset = queryset.order_by(Lower(ordering[1:])).reverse()
else:
queryset = queryset.order_by(Lower(ordering))
return queryset
The problem with this pattern is it doesn't work for ordering multiple fields. The only way to do this would be to pass the descending
argument directly to Lower
, and lower fails with anything like '-myfield'
like the normal Django ORM does for descending ordering.
Here's the current pattern, which accepts multiple arguments for ordering, but does not handle descending:
class OrderingQuerySetMixin(object):
"""Return a case-insensitive ordered queryset."""
def eval_param(self, param):
if param.startswith('-'):
return param[1:]
else:
return param
def get_queryset(self):
queryset = self.queryset
ordering = self.request.query_params.get('ordering', None)
if ordering:
queryset = queryset.order_by(
*[Lower(self.eval_param(p)) for p in ordering.split(',')]
)
return queryset
Upvotes: 1
Views: 902
Reputation: 381
#Import Lower function
from django.db.models.functions import Lower
#For Ascending order
queryset.order_by(Lower('field_name'))
#For Descending order
queryset.order_by(Lower('field_name').desc())
Upvotes: 2