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

Django REST Framework嵌套序列化器无法显示关联数据

问题

在使用Django REST Framework时,嵌套序列化器无法显示关联数据。演示应用中的嵌套序列化器可正常工作,但主应用中无法正常显示。已尝试添加related_name、使用depth选项确认数据配置正确,但均无效。

相关代码如下:

模型代码

class Location(models.Model):
    user = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
    name = models.CharField("Full name", max_length=100,)
    geolocation = models.PointField()
    address1 = models.CharField("Address line 1", max_length=1024,)
    address2 = models.CharField("Address line 2", null=True, max_length=1024,)
    city = models.CharField("City", max_length=50,)
    STATES = [
        ("AL", "Alabama"),
        # 省略其他州选项
        ("WY", "Wyoming")
    ]
    state = models.CharField(max_length=14, choices=STATES, default='AL')
    zip_code = models.CharField("ZIP / Postal code", max_length=12,)
    country = models.CharField("Country", max_length=3,)
    website = models.URLField(max_length=200, null=True)

    def __str__(self):
        return self.name


class FavoriteLocation(models.Model):
    nickname = models.CharField("Nickname", max_length=24,)
    user = models.ForeignKey(User, related_name='user_details', null=False, on_delete=models.CASCADE)
    location = models.ForeignKey(Location, related_name='location_details', null=False, on_delete=models.CASCADE)
    
    def __str__(self):
        return self.nickname

序列化器代码

class LocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = ['id', 'geolocation', 'address1', 'address2', 'city', 'state', 'country', 'website']

class FavoriteLocationSerializer(serializers.ModelSerializer):
    location_details = LocationSerializer(many=True, read_only=True)
    class Meta:
        model = FavoriteLocation
        fields = ['id', 'nickname', 'user', 'location', 'location_details']

视图集与路由

# 视图集
class FavoriteLocationViewset(viewsets.ModelViewSet):
    permission_class = (IsAuthenticated,)
    queryset = FavoriteLocation.objects.all()
    serializer_class = FavoriteLocationSerializer 

# 路由
router.register(r'favoritelocation', FavoriteLocationViewset, basename='favorite_locations')

当前JSON响应输出:

[
    {
        "id": 2,
        "nickname": "My Favorite Restaurant",
        "user": 2,
        "location": 2
    }
]
解决方案

错误原因

你搞反了关联关系的方向:

  • related_name='location_details'是定义在FavoriteLocation的location外键上,它表示从Location到FavoriteLocation的反向关联——即通过一个Location对象,可以用location.location_details.all()获取所有关联到它的FavoriteLocation实例(一对多关系)。
  • 但你在FavoriteLocationSerializer中声明location_details = LocationSerializer(...),相当于试图从FavoriteLocation实例获取它关联的多个Location,这和实际的数据库关系完全相反(每个FavoriteLocation只关联一个Location)。

修复方法

修改FavoriteLocationSerializer,直接对location字段使用嵌套序列化器:

class FavoriteLocationSerializer(serializers.ModelSerializer):
    # 直接对关联的location字段使用序列化器
    location = LocationSerializer(read_only=True)
    class Meta:
        model = FavoriteLocation
        # 字段中只保留嵌套后的location,不需要原外键字段
        fields = ['id', 'nickname', 'user', 'location']

如果需要同时保留外键ID和嵌套的详情数据,可以自定义字段名:

class FavoriteLocationSerializer(serializers.ModelSerializer):
    # 用source指定关联的location字段,自定义字段名
    location_details = LocationSerializer(source='location', read_only=True)
    class Meta:
        model = FavoriteLocation
        fields = ['id', 'nickname', 'user', 'location', 'location_details']

修改后,接口响应会包含完整的Location关联数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 06:43:11