Django Rest Framework双层嵌套序列化器问题
解决在ListingSerializer中获取所属Unit所有Price的问题
问题背景
你有三层关联的Django模型:Unit -> Listing -> Price,现在需要在Listing的序列化器里拿到当前Listing所属Unit下的所有Price(也就是该Unit下所有Listing的Price记录),之前用source="unit__listings__prices"的方式行不通,下面给两种可行的解决办法:
方法一:用SerializerMethodField自定义字段
这是最直接的实现方式,自己写方法来查询并序列化目标数据:
# serializers.py class PriceSerializer(serializers.ModelSerializer): class Meta: model = Price fields = ["amount"] class ListingSerializer(serializers.ModelSerializer): # 自定义字段名,避免和当前Listing自己的prices混淆 unit_all_prices = serializers.SerializerMethodField(read_only=True) class Meta: model = Listing # 按需添加你需要的其他字段 fields = ["number_of_bedrooms", "unit_all_prices"] def get_unit_all_prices(self, obj): # 通过当前Listing关联的Unit,筛选所有属于该Unit的Price all_prices = Price.objects.filter(listing__unit=obj.unit) return PriceSerializer(all_prices, many=True).data
方法二:预查询优化性能(避免N+1查询)
如果是在列表接口中使用上面的方法,会触发大量重复查询,建议在视图层提前预加载关联数据:
# views.py from django.db.models import Prefetch from rest_framework.viewsets import ReadOnlyModelViewSet from .models import Listing, Price from .serializers import ListingSerializer class ListingViewSet(ReadOnlyModelViewSet): queryset = Listing.objects.select_related('unit').prefetch_related( # 预加载Unit下所有Listing的Price Prefetch('unit__listings__prices', queryset=Price.objects.all()) ) serializer_class = ListingSerializer
然后修改序列化器里的方法,直接从预加载的缓存里取数据,不用再发新查询:
# serializers.py def get_unit_all_prices(self, obj): prices = [] # 遍历Unit下的所有Listing,收集它们的Price for listing in obj.unit.listings.all(): prices.extend(listing.prices.all()) return PriceSerializer(prices, many=True).data
为什么原来的source写法无效?
DRF的source参数只能处理单层级的关联(不管是正向还是反向),没办法直接解析unit__listings__prices这种跨两层的一对多关联来返回集合数据,所以必须用自定义方法来处理。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

