You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 08:24:18