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

DRF中如何基于关联模型字段生成自定义字段并实现排序?

解决Django API自定义拼接字段排序问题

步骤1:修改过滤器类,添加full_name注解

在JobApplicationFilter里重写get_queryset方法,用Concat函数拼接first_name和last_name生成full_name字段,同时可按需添加full_name的筛选器:

from django.db.models import Value, CharField
from django.db.models.functions import Concat
import django_filters

class JobApplicationFilter(django_filters.FilterSet):
    gender = django_filters.CharFilter(field_name='job_seeker__personaldetails__gender')    
    age = django_filters.NumberFilter(field_name='job_seeker__personaldetails__age', lookup_expr='lte')
    experience = django_filters.NumberFilter(field_name='experience', lookup_expr='lte')
    # 可选:支持按full_name模糊搜索
    full_name = django_filters.CharFilter(field_name='full_name', lookup_expr='icontains')

    class Meta:
        model = JobApplication 
        fields = ['gender', 'age', 'experience', 'full_name']

    def get_queryset(self, queryset):
        # 拼接姓名字段,中间加空格
        queryset = queryset.annotate(
            full_name=Concat(
                'job_seeker__personaldetails__first_name',
                Value(' '),
                'job_seeker__personaldetails__last_name',
                output_field=CharField()
            )
        )
        return super().get_queryset(queryset)

步骤2:更新视图的排序字段列表

把full_name加入ordering_fields,让OrderingFilter能识别这个自定义字段:

from rest_framework import generics
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter

class JobApplicantFilterListView(generics.ListAPIView):
   
    serializer_class = JobApplicationSerializer
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = JobApplicationFilter
    pagination_class = CustomPageNumberPagination
    # 新增full_name到排序字段
    ordering_fields = ['age','experience', 'full_name']
    # 可选:设置默认排序为full_name升序
    # ordering = ['full_name']

步骤3:(可选)在序列化器中返回full_name

如果需要API响应里返回拼接后的全名,给序列化器添加只读字段:

from rest_framework import serializers

class JobApplicationSerializer(serializers.ModelSerializer):
    full_name = serializers.CharField(source='full_name', read_only=True)

    class Meta:
        model = JobApplication
        fields = ['id', 'job_post', 'job_seeker', 'applied_date', 'experience', 'full_name']

常见问题排查

之前annotate没生效,大概率是这两个原因:

  • 注解逻辑放在了视图的get_queryset里,但过滤器的get_queryset重新获取了原始查询集,覆盖了注解;
  • 没把full_name加入ordering_fields,导致排序组件识别不了这个字段。

测试排序请求

现在可以通过请求参数控制排序:

  • 升序排序:GET /your-api-endpoint/?ordering=full_name
  • 降序排序:GET /your-api-endpoint/?ordering=-full_name

内容的提问来源于stack exchange,提问作者altu_faltu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:31:17