我已尝试在其他地方发布了一些针对此问题的解决方案,但没有运气。看起来DRF本身不支持它。有人有关于如何做到这一点的建议吗?
我有reports
模型和section
模型。部分定义如下:
class Section(models.Model):
title = models.CharField(max_length=255)
report = models.ForeignKey(Report)
order = models.PositiveIntegerField()
section = models.ForeignKey('self', related_name='section_section', blank=True, null=True)
content = models.TextField(blank=True)
我希望在报告中显示数据:
[
{
"id": 1,
"title": "test",
"subtitle": "test",
"section_set": [
{
"id": 1,
"title": "test",
"report": 1,
"order": 1,
"section_set": [
{
"id": 1,
"title": "test",
"report": 1,
"order": 1,
"section": null,
"content": "<p>test</p>"
},
{
"id": 2,
"title": "test",
"report": 1,
"order": 1,
"section": 2,
"content": "<p>test</p>"
},
{
"id": 3,
"title": "test",
"report": 1,
"order": 1,
"section": null,
"content": "<p>test</p>"
}
],
"content": "<p>test</p>"
},
{
"id": 2,
"title": "test",
"report": 1,
"order": 1,
"section": 2,
"content": "<p>test</p>"
},
{
"id": 3,
"title": "test",
"report": 1,
"order": 1,
"section": null,
"content": "<p>test</p>"
}
]
}
]
我当前(尝试过)的实现如下所示:
class SubsectionSerializer(serializers.ModelSerializer):
class Meta:
model = Section
class SectionSerializer(serializers.ModelSerializer):
section = SubsectionSerializer()
class Meta:
model = Section
fields = ('id', 'title', 'report', 'order', 'section', 'content')
class CountryReportSerializer(serializers.ModelSerializer):
section_set = SectionSerializer(many=True)
class Meta:
model = CountryReport
fields = ('id', 'title', 'subtitle', 'section_set')
class MapsSerializer(serializers.ModelSerializer):
class Meta:
model = Map
fields = ('id', 'country', 'map_image', 'report')
但输出如下:
{
"id": 1,
"title": "test",
"subtitle": "test",
"section_set": [
{
"id": 1,
"title": "Section 1",
"report": 1,
"order": 1,
"section": null,
"content": "<p>test</p>"
},
{
"id": 2,
"title": "Section 2",
"report": 1,
"order": 1,
"section": null,
"content": "<p>test</p>"
},
{
"id": 3,
"title": "Subsection 1",
"report": 1,
"order": 1,
"section": {
"id": 1,
"title": "Section 1",
"order": 1,
"content": "<p>test</p>",
"report": 1,
"section": null
},
"content": "<p>test</p>"
}
]
}
答案 0 :(得分:2)
您定义子部分的方式并不会将其链接到您的部分字段,就像错误建议一样。您是否尝试过像这样定义序列化程序:
class SectionSerializer(serializers.ModelSerializer):
class Meta:
model = Section
因为Section有一个FK to section,所以应该按照你对序列化程序的期望返回它。
要确保此序列化程序返回的JSON结果包含嵌套的JSON对象,而不是仅包含FK,您可以采用两种路径:
1),depth=
class SectionSerializer(serializers.ModelSerializer):
class Meta:
model = Section
depth=2
这将关闭FK,构建JSON对象,直到达到您指定的深度。
2)定义SubSerializer来处理JSON对象的创建:
class SubsectionSerializer(serializers.ModelSerializer):
class Meta:
model = Section
class SectionSerializer(serializers.ModelSerializer):
section = serializers.SubsectionSerializer()
class Meta:
model = Section
fields = ('id', 'title', 'report', 'order', 'section', 'content')
------------------------ EDIT ---------------------- -----
为清楚起见,重命名模型的相关位可能是有意义的:
class Section(models.Model):
title = models.CharField(max_length=255)
report = models.ForeignKey(Report)
order = models.PositiveIntegerField()
parent_section = models.ForeignKey('self', related_name='child_sections', blank=True, null=True)
content = models.TextField(blank=True)
使用新名称,您应该能够使用以下序列化程序:
class SectionSerializer(serializers.ModelSerializer):
child_sections = serializers.SubsectionSerializer(many=True)
class Meta:
model = Section
fields = ('id', 'title', 'report', 'order', 'child_sections', 'content')
答案 1 :(得分:2)
使用以下解决方案:
class RecursiveField(serializers.Serializer):
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
class SectionSerializer(serializers.ModelSerializer):
children = RecursiveField(many=True)
class Meta:
model = Section
fields = ('id', 'order', 'title', 'content', 'parent', 'children')
class CountryReportSerializer(serializers.ModelSerializer):
section_set = serializers.SerializerMethodField('get_parent_sections')
@staticmethod
def get_parent_sections(self, obj):
parent_sections = Section.objects.get(parent=None, pk=obj.pk)
serializer = SectionSerializer(parent_sections)
return serializer.data
class Meta:
model = CountryReport
fields = ('id', 'title', 'subtitle', 'section_set')
class MapsSerializer(serializers.ModelSerializer):
class Meta:
model = Map
fields = ('id', 'country', 'map_image', 'report')
答案 2 :(得分:1)
对于任何想要创建嵌套树状结构的人来说,这就是DRF 3.12.1对我有用的:
# Model class
class Foo:
foo = models.ForeignKey('Foo', null=True, blank=True)
# Serializer class
class FooSerializer(serializers.ModelSerializer):
foo = serializers.SerializerMethodField()
def get_foo(self, obj):
return FooSerializer(obj.foo).data if obj.foo else None
class Meta:
model = Foo
fields = '__all__'
这将给出如下响应:
[
{
"id": 105,
"a": {
"id": 106,
"a": null,
}
}
]
答案 3 :(得分:0)
KISS方法,RecursiveField序列化只返回值
\'
在model.py
中class RecursiveField(serializers.ModelSerializer):
def to_representation(self, value):
serializer_data = TypeSerializer(value, context=context).data
return serializer_data
class Meta:
model = Type
fields = '__all__'
class TypeSerializer(serializers.ModelSerializer):
extends_type = RecursiveField(allow_null=True)
class Meta:
model = Type
fields = '__all__'
你可以轻松地进入循环,为了避免这种情况,我们可以将TypeSerializer复制到SubTypeSerializer,并在上下文中使用on key counter计数或控制
下class Type(models.Model):
id = models.AutoField(primary_key=True)
extends_type = models.ForeignKey('self', models.SET_NULL, null=True)