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

