首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Django Rest框架:自定义API响应

Django Rest框架:自定义API响应
EN

Stack Overflow用户
提问于 2018-06-27 01:20:55
回答 2查看 1K关注 0票数 0

我有与Source对象具有ManyToMany关系的Char对象。因为一个Char可以出现在许多源中,并且许多源可以包含多个字符。MtM关系通过一个through表,该表也包含页码。在我使用Django REST框架构建的API响应中,我希望避免为每个Char解析完整的源代码标题、作者等。相反,为了减小JSON响应的大小,我希望通过id来引用它,并包含一个sources部分,这样客户端就可以查找它。

例如,访问/api/char/26的客户端应该会得到以下响应:

代码语言:javascript
复制
"chars": [
    {
        "id": 26,
        "name": "龜",
        "locations": [
            {
                "page": 136,
                "source": 1
            },
            {
                "page": 162,
                "source": 1
            }
        ]
    }
],
"sources": [
    {
        "id": 1,
        "title": "Bruksanvisning Foamglass",
        "author": "Bluppfisk"
    }
]

以下是API视图:

代码语言:javascript
复制
class CharAPIView(generics.RetrieveAPIView):
    queryset = Char.objects.all()
    serializer_class = CharSerializer

和序列化程序:

代码语言:javascript
复制
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值。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-27 18:38:03

最后,通过覆盖视图的retrieve方法,我最终解决了这个问题,如下所示。

代码语言:javascript
复制
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,
        })
票数 1
EN

Stack Overflow用户

发布于 2018-06-27 05:25:16

这可以通过在CharSerializer上使用另一个SerializerMethodField并创建一个SourceSerializer来完成;不需要对GenericAPIView or RetrieveModelMixin的基方法进行扩展。

代码语言:javascript
复制
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查询来代替查询集。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51048407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档