Django REST Framework序列化器无法显示关联模型数据求助
我来帮你解决这个问题!你遇到的核心问题是Django ORM默认的反向关联名称和你序列化器里使用的字段名不匹配,导致DRF无法找到对应的关联数据。另外你的模型里还有一个拼写错误需要先修复,我一步步给你讲清楚:
第一步:修复模型中的拼写错误
先看你的EntityRangeData模型,外键字段名拼错了,这个错误会导致后续关联数据无法正确关联,必须先修正:
# 原错误代码 class EntityRangeData(Data): enityrange = models.ForeignKey(EntityRange, on_delete=models.CASCADE) # 修正后 class EntityRangeData(Data): entityrange = models.ForeignKey(EntityRange, on_delete=models.CASCADE)
第二步:解决反向关联名称不匹配的问题
Django ORM对于外键的反向关联,默认名称是小写模型名_set,比如:
- Post和Block的关联:Post的反向字段默认是
block_set,但你在PostSerializer里用了blocks - Block和InlineStyleRange的关联:Block的反向字段默认是
inlinestylerange_set,你用了inlineStyleRanges - Block和EntityRange的关联:Block的反向字段默认是
entityrange_set,你用了entityRanges
你有两种方法解决这个问题:
方法一:修改模型外键,添加related_name(推荐,更直观)
直接在模型的外键字段上指定related_name,让它和你序列化器里的字段名一致:
# models.py class Block(models.Model): post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='blocks') # 添加反向关联名 key = models.CharField(max_length=255) text = models.TextField() type = models.CharField(max_length=90) depth = models.IntegerField(default=0) class InlineStyleRange(models.Model): block = models.ForeignKey(Block, on_delete=models.CASCADE, related_name='inlineStyleRanges') # 添加反向关联名 offset = models.IntegerField() length = models.IntegerField() style = models.CharField(max_length=90) class EntityRange(models.Model): block = models.ForeignKey(Block, on_delete=models.CASCADE, related_name='entityRanges') # 添加反向关联名 offset = models.IntegerField() length = models.IntegerField() key = models.IntegerField() class EntityEntry(models.Model): key = models.IntegerField() block= models.ForeignKey(Block, on_delete=models.CASCADE, related_name='entityEntries') # 同理添加反向关联名 type = models.CharField(max_length=90) mutability = models.CharField(max_length=90)
方法二:不修改模型,在序列化器里指定source
如果你不想改动模型,可以在序列化器的字段上通过source参数指定默认的反向关联名称:
# Serializers.py class BlockSerializer(serializers.ModelSerializer): # 指定source为默认的反向关联名称 inlineStyleRanges = InlineStyleRangeSerializer(many=True, required=False, source='inlinestylerange_set') entityRanges = EntityRangeSerializer(many=True, required=False, source='entityrange_set') class Meta: model = models.Block fields = "__all__" class PostSerializer(serializers.ModelSerializer): # 指定source为默认的反向关联名称 blocks = BlockSerializer(many=True, required=False, read_only=True, source='block_set') class Meta: model = models.Post fields = "__all__"
第三步:修正Entity相关的序列化器
你的EntityEntrySerializer和EntityRangeSerializer里的data字段也有问题,因为EntityEntryData和EntityRangeData是多对一关联到对应的实体,所以需要加上many=True,并且指定正确的source:
# Serializers.py class EntityEntryDataSerializer(serializers.ModelSerializer): class Meta: model = models.EntityEntryData fields = "__all__" class EntityEntrySerializer(serializers.ModelSerializer): # 一个EntityEntry可以对应多个EntityEntryData,所以加many=True并指定反向关联名 data = EntityEntryDataSerializer(many=True, required=False, source='entityentrydata_set') class Meta: model = models.EntityEntry fields = "__all__" class EntityRangeDataSerializer(serializers.ModelSerializer): class Meta: model = models.EntityRangeData fields = "__all__" class EntityRangeSerializer(serializers.ModelSerializer): # 同理,加many=True和正确的source data = EntityRangeDataSerializer(many=True, required=False, source='entityrangedata_set') class Meta: model = models.EntityRange fields = "__all__"
最后验证
做完以上修改后,如果修改了模型,记得重新迁移数据库:
python manage.py makemigrations python manage.py migrate
然后确保你的数据库里已经有Post关联的Block、Block关联的InlineStyleRange等数据,这样DRF就能正确返回嵌套的关联内容了。比如现在你的Post序列化后应该会包含blocks字段,每个block里又包含inlineStyleRanges和entityRanges等数据。
内容的提问来源于stack exchange,提问作者chaulap
相关产品推荐
相关产品推荐

