如何在Django中获取min_price对应的Price关联数据并序列化展示?
解决方法:获取对应最低价格的Price对象数据
你遇到的问题有两个核心原因:一是之前的prefetch_related只是预取了该手机的所有Price记录,而非对应最低价格的那条;二是自定义序列化字段sdata没有被包含在输出里(因为你用了fields='__all__',它只会包含模型本身的字段,不会自动包含自定义嵌套字段)。
下面是完整的分步解决方案:
第一步:修改QuerySet,精准筛选对应最低价格的Price记录
我们需要用Subquery和Prefetch来定位每个手机对应的最低价格记录,而非预取所有价格数据。在你的views.py中修改如下:
from django.db.models import Subquery, OuterRef, Min from django.db.models.query import Prefetch from rest_framework import generics class PhoneAPI(generics.ListAPIView): serializer_class = PhoneSerializer def get_queryset(self): # 子查询1:获取每个手机的最低价格数值 min_price_subquery = Price.objects.filter( phone=OuterRef('pk') ).values('phone').annotate(min_p=Min('price')).values('min_p') # 子查询2:筛选出对应最低价格的Price完整记录 lowest_price_queryset = Price.objects.filter( phone=OuterRef('pk'), price=Subquery(min_price_subquery[:1]) ) # 给Phone对象预取筛选后的最低价格记录,存入自定义属性lowest_price_obj return Phone.objects.annotate( min_price=Min('price__price') ).prefetch_related( Prefetch( 'price_set', queryset=lowest_price_queryset, to_attr='lowest_price_obj' ) )
第二步:修改序列化器,展示关联的Price数据
现在需要在PhoneSerializer中添加字段,序列化我们预取的lowest_price_obj,同时注意显式列出所有需要的字段(不要用fields='__all__'):
from rest_framework import serializers from .models import Phone, Price class PriceSerializer(serializers.ModelSerializer): phone = serializers.StringRelatedField() market = serializers.StringRelatedField() class Meta: model = Price fields = ('id', 'price', 'date', 'market', 'phone') class PhoneSerializer(serializers.ModelSerializer): min_price = serializers.IntegerField() # 序列化预取的最低价格对象,many=False表示单个记录(若有多个相同最低价可改为True) lowest_price = PriceSerializer(source='lowest_price_obj', many=False, read_only=True) class Meta: model = Phone # 显式列出所有需要返回的字段,包括自定义的lowest_price fields = ['id', 'min_price', 'name', 'description', 'image', 'slug_phone', 'lowest_price']
最终效果
修改完成后,你的API输出会新增lowest_price字段,里面包含对应最低价格的date、market等完整Price数据,示例输出如下:
{"count":7,"next":null,"previous":null,"results":[ {"id":10,"min_price":718,"name":"SAMSUNG Galaxy S10", "description":"SAMSUNG Galaxy S10, Smartphone, 128 GB, Prism Black, Dual SIM", "image":"http://127.0.0.1:8000/media/phone_img/galaxy_s10.jpg", "slug_phone":"samsung-galaxy-s10", "lowest_price":{ "id":5, "price":"718.00", "date":"2024-05-20", "market":"某电商平台", "phone":"SAMSUNG Galaxy S10" } }, ... ]}
如果某款手机存在多条价格相同的最低记录,只需把PhoneSerializer中的many=False改为many=True,即可返回所有符合条件的Price记录列表。
内容的提问来源于stack exchange,提问作者black_hole_sun
相关产品推荐
相关产品推荐

