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

如何在序列化深度2的关联模型时跳过深度1的中间模型?

Django REST Framework 跨关联模型直接序列化用户信息问题

问题场景

有三个外键关联的模型,关联关系为 Order -> Customer -> User,需要在订单的ViewSet序列化输出时,直接展示对应的User信息,不包含中间的Customer层级。

模型定义

from django.db import models

class Order(models.Model):
    customer = models.ForeignKey("customers.Customer", on_delete=models.CASCADE)

class Customer(models.Model):
    user = models.ForeignKey("users.User", on_delete=models.CASCADE)

class User(models.Model):
    name = models.CharField(max_length=64)

尝试的序列化器与视图

序列化器代码

from rest_framework import serializers
from .models import Order, User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["name"]

class OrderSerializer(serializers.ModelSerializer):
    user = UserSerializer(source="customer__user", read_only=True)

    class Meta:
        model = Order
        fields = ["id", "user"]

视图集代码

from rest_framework import viewsets
from .models import Order
from .serializers import OrderSerializer

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

问题现象

  • 期望输出:
[
    {"id": 1, "user": {"name": "John"}},
    {"id": 2, "user": {"name": "Mary"}}
]
  • 实际输出:
[
    {"id": 1},
    {"id": 2}
]

若通过中间的Customer序列化器中转,虽然能正常输出,但会包含多余的Customer层级:

中转序列化器代码

class CustomerSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)

    class Meta:
        model = Customer
        fields = ["user"]

class OrderSerializer(serializers.ModelSerializer):
    customer = CustomerSerializer(read_only=True)

    class Meta:
        model = Order
        fields = ["id", "customer"]

中转方式输出结果

[
    {"id": 1, "customer": {"user": {"name": "John"}}},
    {"id": 2, "customer": {"user": {"name": "Mary"}}}
]

解决方案

方法1:使用SerializerMethodField手动序列化用户信息

修改OrderSerializer,通过自定义方法获取并序列化User对象:

class OrderSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField()

    def get_user(self, obj):
        return UserSerializer(obj.customer.user).data

    class Meta:
        model = Order
        fields = ["id", "user"]

同时为避免N+1查询性能问题,在视图集的queryset中预取关联数据:

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.select_related('customer__user')
    serializer_class = OrderSerializer

方法2:使用属性链式访问替代双下划线写法

直接使用属性链式访问作为source,替代ORM查询的双下划线语法:

class OrderSerializer(serializers.ModelSerializer):
    user = UserSerializer(source="customer.user", read_only=True)

    class Meta:
        model = Order
        fields = ["id", "user"]

同样需要在queryset中添加select_related('customer__user')优化查询性能。

问题原因说明

原代码中source="customer__user"的双下划线是ORM查询语法,但嵌套序列化器的source参数不支持自动解析该语法来获取关联对象,导致无法正确读取User实例,因此对应字段无输出。使用属性链式访问customer.user或SerializerMethodField可以直接获取到关联的User实例,完成序列化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 13:17:34