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
相关产品推荐
相关产品推荐

