手动组合多个Django QuerySet,并使用DRF序列化结果

时间:2016-09-16 17:58:38

标签: django

我已经研究了几天了。不幸的是,到目前为止我找到的所有提议的解决方案都不适合我。

我希望手动将两个Django QuerySets组合成一个Django模型,然后我想使用Django Rest Framework序列化程序进行序列化。然后我使用序列化程序输出JSON。

我在SO上找到了各种解决方案,建议使用itertools和chain,但目前还不清楚如何序列化链的结果。

请注意,我的目标是用于Web应用程序性能目的。每个QuerySet都可以独立工作,但它需要两个单独的Ajax调用来检索结果。我更愿意只进行一次Ajax调用,在服务器端手动组合结果,然后返回组合的JSON。

这个SO答案很接近,但我无法弄清楚如何使用DRF序列化器序列化链的结果。

2 个答案:

答案 0 :(得分:5)

经过几天谷歌搜索这个问题的答案后,我终于偶然发现this page,这解释了如何做我想做的事情。我已经在这里发布了自己的答案,以防其他人遇到同样的问题。

这项技术现在看起来很简单,我理解它,但我很难在网上找到描述这种技术的东西。基本上,您将多个查询集链接在一起,然后将链转换为Python列表。然后迭代列表,手动调用正确的序列化程序,并附加到字典。然后你可以将字典转储到JSON。

我已发布相关代码以防链接失效:

    def get_queryset(self):
        queryset_a = Post.objects.all()
        queryset_b = FriendRequest.objects.filter(is_unanswered=True)

        # Create an iterator for the querysets and turn it into a list.
        results_list = list(chain(queryset_a, queryset_b))

        # Optionally filter based on date, score, etc.
        sorted_list = sorted(results_list, key=lambda instance: -instance.date_created)

        # Build the list with items based on the FeedItemSerializer fields
        results = list()
        for entry in sorted_list:
            item_type = entry.__class__.__name__.lower()
            if isinstance(entry, Post):
                serializer = PostSerializer(entry)
            if isinstance(entry, FriendRequest):
                serializer = FriendRequestSerializer(entry)

            results.append({'item_type': item_type, 'data': serializer.data})

        return results

答案 1 :(得分:2)

两个查询集是否来自同一个模型?如果是这样,你可以说:

qs1 = Potato.objects.filter(size = PotatoSize.large)
qs2 = Potato.objects.filter(color = VegetableColor.brown)
combined_qs = qs1 | qs2

如果它们来自不同的模型,但模型通过继承相互关联(即一个是抽象的子类),你仍然可以这样做:

qs1 = RootVegetable.objects.filter(color = VegetableColor.brown)
qs2 = Potato.objects.filter(size = PotatoSize.large)

qs2.model = RootVegetable

# this will return a QS of RootVegetables
combined_qs = qs1 | qs2

然后,您可以序列化组合的查询集。