Django REST Framework中如何按姓氏实现自定义排序?
按姓氏排序的自定义实现方案
1. 完善自定义排序过滤器类
首先需要实现get_ordering方法,当请求指定按surname排序时,从name字段中提取姓氏(默认假设姓名以空格分隔,姓氏为最后一部分),并基于该值完成排序。
先导入必要模块:
from django.db.models import Func, F, Value from django_filters.rest_framework import OrderingFilter
然后完善SurnameOrdering类:
class SurnameOrdering(OrderingFilter): # 声明允许的排序字段,新增surname选项 ordering_fields = ['name', 'surname'] def get_ordering(self, request, queryset, view): # 获取原生排序参数 ordering = super().get_ordering(request, queryset, view) if not ordering: return ordering modified_ordering = [] for field in ordering: # 判断是否是按姓氏排序的请求 if field.lstrip('-') == 'surname': # 提取name字段最后一个部分作为姓氏(适配PostgreSQL) surname_expr = Func(F('name'), Value(' '), Value(-1), function='SPLIT_PART') # 保留原排序方向(升序/降序) if field.startswith('-'): modified_ordering.append(-surname_expr) else: modified_ordering.append(surname_expr) else: modified_ordering.append(field) return modified_ordering
若使用MySQL数据库,
SPLIT_PART函数不兼容,需替换为MySQL的字符串处理逻辑:# MySQL版本:提取最后一个空格后的内容作为姓氏 surname_expr = Func( F('name'), Value(' '), function='SUBSTRING_INDEX', template="%(function)s(%(expressions)s, ' ', -1)" )
2. 更新视图配置
将原视图中的OrderingFilter替换为自定义的SurnameOrdering,并调整排序字段配置:
from rest_framework import generics from django_filters import filters from .models import Contact from .serializers import ContactSerializer class ContactListView(generics.ListAPIView): queryset = Contact.objects.all() serializer_class = ContactSerializer # 替换为自定义排序过滤器 filter_backends = (filters.SearchFilter, SurnameOrdering) # 允许按name和surname字段排序 ordering_fields = ['name', 'surname'] search_fields = ('name',)
3. 使用方式
现在可以通过请求参数指定按姓氏排序:
- 升序:
GET /contacts/?ordering=surname - 降序:
GET /contacts/?ordering=-surname
额外说明
- 如果是中文姓名(格式为"姓 名"),需要调整姓氏提取逻辑,改为取第一个空格前的内容。
- 若姓名包含中间名(多空格),上述逻辑仍会取最后一个部分作为姓氏,符合英文姓名的通用规则。
内容的提问来源于stack exchange,提问作者tarp20
相关产品推荐
相关产品推荐

