序列化多个模型并在一个 json 响应中发送全部 django rest 框架

Posted

技术标签:

【中文标题】序列化多个模型并在一个 json 响应中发送全部 django rest 框架【英文标题】:Serialize multiple models and send all in one json response django rest framework 【发布时间】:2017-12-12 04:20:37 【问题描述】:

这个问题被要求扩展并填补这个问题:Return results from multiple models with Django REST Framework

我的目标是返回一个 json 对象,我将使用该对象在我的 html 代码中动态填充各种 select 语句中的选项。

所以我想从模型 a 中获取一个属性,从模型 b 中获取另一个属性等

然后我想要属性 a 和 b 和 c 等的所有值

在一个值中作为一个 JSON 数组到一个键所以

json = 
    modelA: 'atter1, atter2, atter3
    modelB: 'atter1, atter2, atter3
    model..:you get the point

上面引用的帖子中的这一部分是有道理的:

class TimelineViewSet(viewsets.ModelViewSet):
    """
    API endpoint that lists all tweet/article objects in rev-chrono.
    """
    queryset = itertools.chain(Tweet.objects.all(), Article.objects.all())
    serializer_class = TimelineSerializer

这不是什么:

class TimelineSerializer(serializers.Serializer):
    pk = serializers.Field()
    title = serializers.CharField()
    author = serializers.RelatedField()
    pub_date = serializers.DateTimeField()

如何将单独的模型属性设置为正确的 json 键?

我假设它类似于序列化器关系,但这些值不通过 onetoone、onetomany 或多对多相互关联。我只想一次获取所有这些信息,而不是为每个值创建一个 api。

我是一个迷路的小女孩,我请求你帮我找到回家的路。

【问题讨论】:

【参考方案1】:

如果你合理地设计你的响应格式,你会发现在 Django REST 框架中事情变得更容易了。

目前似乎有点模糊,但我建议如下:


    "tweets": [
        "tweet_attr_A": value_1, ...,  // first tweet
        "tweet_attr_A": value_2, ...,  // second tweet
        //etc
    ],
    "articles": [
        "id": 1, ...,  // first article
        "id": 2, ...,  // second article
        //etc
    ]

我们可以用三个序列化器来表达这一点,比如:

class TweetSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tweet

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article

class TimelineSerializer(serializers.Serializer):
    tweets = TweetSerializer(many=True)
    articles = ArticleSerializer(many=True)

http://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects

然后,因为我们使用的模型不止一个,所以最简单的方法是定义您自己的自定义视图集,而不是试图将其硬塞到 DRF 的神奇 ModelViewSet 类型中。http://www.django-rest-framework.org/api-guide/viewsets/#example

首先我们需要一个对象类型来传递给我们的 TimelineSerializer。它应该有两个属性:tweetsarticles

from collections import namedtuple

Timeline = namedtuple('Timeline', ('tweets', 'articles'))

然后我们将定义自定义视图集来获取推文和文章,实例化一个 Timeline 对象并返回 TimelineSerializer 数据:

class TimelineViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing the Tweets and Articles in your Timeline.
    """
    def list(self, request):
        timeline = Timeline(
            tweets=Tweet.objects.all(),
            articles=Article.objects.all(),
        )
        serializer = TimelineSerializer(timeline)
        return Response(serializer.data)

【讨论】:

嘿伙计,这个答案非常好,非常完整。我想比最初更深层次地感谢你。非常感谢!!!!!! @amazingCarrotSoup 不客气!我一直在考虑添加后续操作:我想到可能在“时间线”的上下文中,您希望所有内容类型一起返回到一个列表中,按日期排序。但这变成了一个数据模型问题:要在从数据库中获取时对它们进行排序,您需要在单个查询中获取它们。并且要在 DRF 中序列化它们,它们都需要是相同类型的对象。因此,这意味着您需要一个可以代表两种类型内容的 TimelineItem 模型,而不是单独的 TweetArticle 模型。 @Anetropic 我明白你的意思,这不是我想要的执行,但我完全理解为什么我必须序列化为同一类型。再次感谢你! @Anentropic 你在timelineitem中有一个例子吗?我试图实现它,但它不起作用。 ***.com/questions/47499261/… @Anentropic 非常详细。请注意,我收到了一条与在没有请求上下文的情况下实例化序列化程序相关的错误消息。 serializer=TimelineSerializer(timeline, context="request": request) 工作。【参考方案2】:

我有同样的情况来序列化多个模型以从每个序列化模型中获取过滤后的输出,以便从一个单一的 api 中使用。我遇到了this module 来实现这个结果。

【讨论】:

以上是关于序列化多个模型并在一个 json 响应中发送全部 django rest 框架的主要内容,如果未能解决你的问题,请参考以下文章

具有反斜杠的 Json 序列化数据

如何使用 alamofire 将服务的响应存储在模型中

JSON 对象模型不使用 JsonProperty 名称

使用 Newtonsoft Json 从流中反序列化多个 json 对象

没有模型 APIView 的 DRF 分页自定义响应

如何检查从服务器收到的响应是 html 还是 json 并在 extjs 中按名称查找 html 表单?