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

在Django序列化时如何获取外键的外键字段值?

解决Django序列化时获取多层关联字段的问题

问题原因

Django自带的serialize函数启用use_natural_foreign_keys=True时,仅会解析当前模型直接关联的外键的natural key,但不会递归解析关联模型的深层外键(比如Service关联的ServiceCategory),所以无法直接拿到分类名称。

解决方案

方案一:修改模型的natural_key定义(推荐,符合Django原生序列化逻辑)

调整Service的natural_key,让它包含关联分类的信息,同时确保ServiceCategory的name字段唯一(保证natural key的唯一性):

class ServiceCategory(models.Model):
    name = models.CharField(max_length=50, unique=True)  # 增加unique约束

    def natural_key(self):
        return (self.name,)  # 用元组返回,符合Django规范

class Service(models.Model):
    service_category = models.ForeignKey(ServiceCategory, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)

    def natural_key(self):
        # 返回包含自身名称和分类名称的元组
        return (self.name, self.service_category.name)

    # 指定natural_key依赖的模型,帮助Django序列化时预取关联数据
    natural_key.dependencies = ['your_app_name.servicecategory']  # 替换为你的实际app名称

保持原序列化代码不变:

data = Request.objects.all()
data = serialize("json", data, use_natural_foreign_keys=True)

此时序列化后的JSON中,每个Service条目会以数组形式包含自身名称和分类名称。

方案二:手动构造序列化数据(无需修改模型)

通过预取关联数据避免N+1查询,然后手动遍历构造需要的数据结构再转成JSON:

from django.db.models import Prefetch
import json

# 预取多层关联数据,提升查询效率
requests = Request.objects.prefetch_related(
    Prefetch('services', queryset=Service.objects.select_related('service_category'))
).all()

# 构造自定义数据结构
result = []
for req in requests:
    service_list = []
    for service in req.services.all():
        service_list.append({
            "name": service.name,
            "service_category": service.service_category.name
        })
    result.append({
        "name": req.name,
        "services": service_list
    })

# 转为JSON格式
data = json.dumps(result)

方案三:使用Django REST Framework序列化器(适合已使用DRF的项目)

如果项目中已经集成DRF,这种方式更灵活,可轻松处理多层关联:

首先定义序列化器:

from rest_framework import serializers
from .models import Request, Service, ServiceCategory

class ServiceCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = ServiceCategory
        fields = ['name']

class ServiceSerializer(serializers.ModelSerializer):
    service_category = ServiceCategorySerializer()
    class Meta:
        model = Service
        fields = ['name', 'service_category']

class RequestSerializer(serializers.ModelSerializer):
    services = ServiceSerializer(many=True)
    class Meta:
        model = Request
        fields = ['name', 'services']

然后执行序列化:

from rest_framework.renderers import JSONRenderer

requests = Request.objects.prefetch_related('services__service_category').all()
serializer = RequestSerializer(requests, many=True)
data = JSONRenderer().render(serializer.data)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:15:43