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
相关产品推荐
相关产品推荐

