我有与Source
对象具有ManyToMany关系的Char
对象。因为一个Char可以出现在许多源中,并且许多源可以包含多个字符。MtM关系通过一个through
表,该表也包含页码。在我使用Django REST框架构建的API响应中,我希望避免为每个Char解析完整的源代码标题、作者等。相反,为了减小JSON响应的大小,我希望通过id来引用它,并包含一个sources
部分,这样客户端就可以查找它。
例如,访问/api/char/26的客户端应该会得到以下响应:
"chars": [
{
"id": 26,
"name": "龜",
"locations": [
{
"page": 136,
"source": 1
},
{
"page": 162,
"source": 1
}
]
}
],
"sources": [
{
"id": 1,
"title": "Bruksanvisning Foamglass",
"author": "Bluppfisk"
}
]
以下是API视图:
class CharAPIView(generics.RetrieveAPIView):
queryset = Char.objects.all()
serializer_class = CharSerializer
和序列化程序:
class CharSerializer(serializers.ModelSerializer):
locations = serializers.SerializerMethodField()
class Meta:
model = Char
fields = ('id', 'name', 'locations',)
depth = 1
def get_locations(self, obj):
qset = CharInSource.objects.filter(char=obj)
return [CharInSourceSerializer(m).data for m in qset]
class CharInSourceSerializer(serializers.ModelSerializer):
class Meta:
model = CharInSource
fields = ('page', 'source',)
问题是我不知道如何连接到generics.RetrieveAPIView
类中,所以它将包含一个相关源代码的列表。我一直在挖掘源代码,但我甚至想不出如何获得pk值。
发布于 2018-06-27 18:38:03
最后,通过覆盖视图的retrieve
方法,我最终解决了这个问题,如下所示。
class CharAPIView(generics.RetrieveAPIView):
queryset = Char.objects.all()
def retrieve(self, *args, **kwargs):
instance = self.get_object()
char = CharSerializer(instance).data
qset = Source.objects.all()
sources = [SourceSerializer(m).data for m in [i for i in instance.location.all()]]
return Response({
'char': char,
'sources': sources,
})
发布于 2018-06-27 05:25:16
这可以通过在CharSerializer
上使用另一个SerializerMethodField
并创建一个SourceSerializer
来完成;不需要对GenericAPIView or RetrieveModelMixin
的基方法进行扩展。
def SourceSerializer(ModelSerializer):
class Meta:
model = Source
fields = ('id', 'title', 'author') # assuming author is not also a
# ForeignKey, otherwise returns an id
def CharSerializer(...):
....
sources = SerializerMethodField()
def get_sources(self, obj):
return SourceSerializer(
Source.objects.filter(chars__in=[obj.id]).distinct(),
many=True).data
class Meta:
fields = (...,'sources')
假设MTM模型related_name的属性是chars
,您可以使用chars__in
并传递一个Char
in列表;在本例中,这是我们引用的单个字符。但是,这将包含每个char对象内的源代码,而不是您在问题中指出的外部。然而,正如我的解决方案所提供的,我想您可能想知道哪些源文件有哪些字符。
如果看不到模型的确切结构,我就不能确定您应该如何检索Source对象。我觉得你也可以用obj.sources.all()
代替SourceSerializer
中笨重的__in
查询来代替查询集。
https://stackoverflow.com/questions/51048407
复制相似问题