如何在DRF中序列化多对多字段?反向关联查询失败求助
问题:从literature_info反向获取关联dataset_info的序列化失败
模型定义
models.py中的三个模型类:
class literature_info(models.Model): pmid = models.CharField(primary_key=True,max_length=25) publication = models.CharField(max_length=50, blank=True, null=True) def __str__(self): return self.pmid class dataset_info(models.Model): dataset_id = models.CharField(primary_key=True,max_length=25) literature = models.ManyToManyField(literature_info, through='literature_dataset', blank=True) def __str__(self): return self.dataset_id class literature_dataset(models.Model): literature_info = models.ForeignKey(literature_info, on_delete=models.CASCADE) dataset_info = models.ForeignKey(dataset_info, on_delete=models.CASCADE)
正向序列化(正常工作)
从dataset_info获取关联文献的序列化器:
class literature_info_serializer(serializers.ModelSerializer): class Meta: model = literature_info fields = "__all__" class dataset_literature_serializer(serializers.ModelSerializer): literature = literature_info_serializer(many=True) class Meta: model = dataset_info fields = ('dataset_id','literature',)
反向序列化问题
尝试从literature_info反向获取关联数据集的序列化器无法正常工作:
class dataset_info_serializer(serializers.ModelSerializer): class Meta: model = dataset_info fields = ('dataset_id',) class literature_dataset_serializer(serializers.ModelSerializer): dataset_info = dataset_info_serializer(many=True) class Meta: model = literature_info fields = ('pmid', 'dataset_info',)
解决方法
问题出在反向关联的字段名称上:在dataset_info的literature多对多字段中,没有显式指定related_name,Django默认的反向关联名称是dataset_info_set(模型名小写+_set),而非你写的dataset_info。
方法一:使用默认反向关联名称修改序列化器
直接把序列化器中的字段名改成默认的dataset_info_set:
class dataset_info_serializer(serializers.ModelSerializer): class Meta: model = dataset_info fields = ('dataset_id',) class literature_dataset_serializer(serializers.ModelSerializer): dataset_info_set = dataset_info_serializer(many=True) class Meta: model = literature_info fields = ('pmid', 'dataset_info_set',)
方法二:显式设置related_name(更优雅)
先修改dataset_info模型中的多对多字段,添加related_name参数自定义反向关联名称:
class dataset_info(models.Model): dataset_id = models.CharField(primary_key=True,max_length=25) # 添加related_name指定反向关联名称 literature = models.ManyToManyField(literature_info, through='literature_dataset', blank=True, related_name='datasets') def __str__(self): return self.dataset_id
然后修改序列化器,使用指定的datasets作为字段名:
class dataset_info_serializer(serializers.ModelSerializer): class Meta: model = dataset_info fields = ('dataset_id',) class literature_dataset_serializer(serializers.ModelSerializer): datasets = dataset_info_serializer(many=True) class Meta: model = literature_info fields = ('pmid', 'datasets',)
两种方法都能解决反向序列化问题,推荐第二种,字段名更直观易懂。
内容的提问来源于stack exchange,提问作者Bioinfotec
相关产品推荐
相关产品推荐

