如何在Django中使用Lower()实现QuerySet的反向排序?
解决Django中带负号的排序参数结合Lower()的问题
你的问题核心在于:直接把负号和Lower()函数拼接的写法在Django中是不生效的——Lower()返回的是数据库函数对象,不是字符串,强行拼接会导致排序逻辑失效,最终fallback到默认的主键排序。
我们可以利用Django数据库函数自带的desc()方法来实现不区分大小写的降序排序,不需要手动拼接负号。下面是修改后的完整代码:
@login_required def merchantgroups_show_all(request): order_by = request.GET.get('order_by', 'name') from django.db.models.functions import Lower # 拆分排序方向和目标字段 if order_by.startswith('-'): target_field = order_by[1:] # 对Lower的结果应用降序 sort_expression = Lower(target_field).desc() else: target_field = order_by # 直接使用Lower做升序排序 sort_expression = Lower(target_field) # 应用排序逻辑 merchant_groups = MerchantGroup.objects.all().order_by(sort_expression) paginator = Paginator(merchant_groups, 20) page = request.GET.get('page') merchant_groups2 = paginator.get_page(page) return render(request, 'monzo/merchantgroups_show_all.html', {'merchant_groups': merchant_groups2})
为什么这个方法有效?
当你调用Lower(target_field).desc()时,Django会自动生成正确的SQL语句,比如对于-name的情况,SQL会是:
ORDER BY LOWER("merchantgroup"."name") DESC
而升序时则生成:
ORDER BY LOWER("merchantgroup"."name") ASC
这样不管是正序还是倒序,都能实现不区分大小写的正确排序。
扩展:支持多字段排序
如果你的需求需要支持多字段排序(比如order_by='-name,created_at'),可以稍微扩展逻辑,拆分每个排序项分别处理:
@login_required def merchantgroups_show_all(request): order_by = request.GET.get('order_by', 'name') from django.db.models.functions import Lower sort_expressions = [] # 拆分多个排序字段 for sort_item in order_by.split(','): if sort_item.startswith('-'): field = sort_item[1:] sort_expressions.append(Lower(field).desc()) else: sort_expressions.append(Lower(field)) merchant_groups = MerchantGroup.objects.all().order_by(*sort_expressions) paginator = Paginator(merchant_groups, 20) page = request.GET.get('page') merchant_groups2 = paginator.get_page(page) return render(request, 'monzo/merchantgroups_show_all.html', {'merchant_groups': merchant_groups2})
内容的提问来源于stack exchange,提问作者rcx935
相关产品推荐
相关产品推荐

