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

Django DRF外键序列化:如何仅返回Node关联的最新Benchmark对象

实现方案

有两种常用实现方案,可根据业务场景按需选择:

方案1:直接在序列化器中处理(实现简单,适合小数据量/单条详情查询场景)

修改NodeSerializer,替换原多关联的benchmark_set字段,手动取最新单条记录序列化即可:

from rest_framework import serializers
from .models import Node, Benchmark

class BenchmarkSerializer(serializers.ModelSerializer):
    class Meta:
        model = Benchmark
        fields = ['benchmark_score', 'benchmarked_at']

class NodeSerializer(serializers.ModelSerializer):
    # 自定义字段取最新基准测试记录,也可保留原字段名benchmark_set
    latest_benchmark = serializers.SerializerMethodField()

    class Meta:
        model = Node
        fields = ['earnings_total', 'node_id', 'data',
                  'online', 'version', 'updated_at', 'created_at', 'latest_benchmark']
    
    def get_latest_benchmark(self, obj):
        # 按测试时间倒序取第一条最新记录
        latest_record = obj.benchmark_set.order_by('-benchmarked_at').first()
        return BenchmarkSerializer(latest_record).data if latest_record else None

注意:该方案在查询Node列表时会产生N+1查询问题,每一条Node都会单独查询一次Benchmark表,数据量大时性能较差。

方案2:预查询优化(性能更好,适合列表批量查询场景)

先在视图层查询Node时预加载最新关联数据,避免N+1问题,再在序列化器直接取值:

视图层QuerySet修改示例

from django.db.models import Max, Prefetch
from rest_framework import viewsets
from .models import Node, Benchmark
from .serializers import NodeSerializer

class NodeViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = NodeSerializer
    
    def get_queryset(self):
        # 预加载每个Node最新的1条Benchmark记录
        return Node.objects.prefetch_related(
            Prefetch(
                'benchmark_set',
                queryset=Benchmark.objects.order_by('-benchmarked_at'),
                to_attr='latest_benchmark_list'
            )
        )

对应序列化器修改

class NodeSerializer(serializers.ModelSerializer):
    latest_benchmark = serializers.SerializerMethodField()

    class Meta:
        model = Node
        fields = ['earnings_total', 'node_id', 'data',
                  'online', 'version', 'updated_at', 'created_at', 'latest_benchmark']
    
    def get_latest_benchmark(self, obj):
        # 直接取预加载好的列表第一条,无需额外查询数据库
        if obj.latest_benchmark_list:
            return BenchmarkSerializer(obj.latest_benchmark_list[0]).data
        return None

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:06:03