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

如何通过Django REST Framework返回多表关联合并的序列化响应数据

Django REST Framework合并两个关联模型序列化响应的实现方法

问题原因

你之前尝试用+拼接两个序列化器的data属性报错,是因为DRF序列化器返回的data是类字典的SerializerData/OrderedDict类型,Python原生不支持字典用+运算符做拼接操作。

方案一:视图层直接合并字典(快速实现)

不需要修改现有模型、序列化器定义,仅需修改视图返回逻辑,用字典解包的方式合并两份序列化结果:

@api_view(['GET'])
def getUserByIDDemo(request, uName, pWord):    
    username = uName
    password = pWord
    userObj = authenticate(request, username=username, password=password)

    # Check if authentication successful
    if userObj is not None:
        login(request, userObj)
        currentUser = Users.objects.get(user = userObj)
        userializer = UserSerializer(currentUser, many = False)
        # 原代码查询条件错误,应该用userID匹配而非customerID
        customer = Customers.objects.get(userID = userializer.data['userID'])
        cserializer = CustomerSerializer(customer, many = False)
        # 字典解包合并,重复的userID字段会保留后面对象里的值,不需要可以手动pop删除
        combined_data = {**userializer.data, **cserializer.data}
        return Response(combined_data)
    else:
        message = "Invalid username and/or password."
        return Response(message)

方案二:自定义联合序列化器(规范写法)

适合需要多处用到合并数据的场景,先调整Customers模型的外键配置,增加反向查询名:

class Customers(models.Model):
    customerID = models.AutoField(primary_key=True)
    # 增加related_name指定反向查询字段名,方便从Users侧查询关联的Customers记录
    userID = models.ForeignKey('Users', on_delete=models.CASCADE, related_name="customer_info")
    occupation = models.TextField()
    blogger = models.BooleanField(default= False)
    def __str__(self):
        return f"ID: {self.customerID}"

新增自定义合并序列化器:

class UserWithCustomerSerializer(ModelSerializer):
    # 声明关联Customers表的字段,通过source指定反向查询路径
    customerID = serializers.IntegerField(source='customer_info.customerID')
    occupation = serializers.CharField(source='customer_info.occupation')
    blogger = serializers.BooleanField(source='customer_info.blogger')

    class Meta:
        model = Users
        fields = [
            'userID', 'firstName', 'lastName', 'gender', 'country', 'city',
            'phoneNumber', 'dob', 'dateJoined', 'role', 'user',
            'customerID', 'occupation', 'blogger'
        ]

调整视图逻辑,直接使用新序列化器完成一次性序列化:

@api_view(['GET'])
def getUserByIDDemo(request, uName, pWord):    
    username = uName
    password = pWord
    userObj = authenticate(request, username=username, password=password)

    if userObj is not None:
        login(request, userObj)
        # select_related预加载关联数据,减少数据库查询次数
        currentUser = Users.objects.select_related('customer_info').get(user = userObj)
        serializer = UserWithCustomerSerializer(currentUser, many=False)
        return Response(serializer.data)
    else:
        message = "Invalid username and/or password."
        return Response(message)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:57:02