是否可以将多个数据库中的多个 django 查询集合并到一个查询集中?

Posted

技术标签:

【中文标题】是否可以将多个数据库中的多个 django 查询集合并到一个查询集中?【英文标题】:Is it possible to merge multiple django querysets from multiple databases into one queryset? 【发布时间】:2019-08-17 00:21:15 【问题描述】:

我想用 django-rest 创建一个 api 来获取事件。例如:我在多个数据库中有一个表事件。对 /events 的 get 请求应该从所有配置的数据库中读取所有事件,并将所有结果聚合到一个查询集中。然后我想序列化查询集并将json返回给用户。

在 settings.py 中,我创建了一个包含 events 表的数据库列表。 我可以通过一个查询从 DATABASE_1 和 DATABASE_2 查询事件。但是当我尝试在一个循环中聚合结果时,我只能从 DATABASE_2 获取事件。所以聚合不起作用。

如何将这些查询集聚合为一个?或者有没有更好的查询多个数据库的解决方案?

settings.py

DATABASES = 
    'default': env.db(),
    'DATABASE_1': env.db('DATABASE_1'),
    'DATABASE_2': env.db('DATABASE_2'),


EVENT_DATABASES = [
    'DATABASE_1',
    'DATABASE_2',
]

urls.py

urlpatterns = [
    path('events/', EventView.as_view())
]

event_view.py

class EventView(APIView):
    serializer_class = EventSerializer

    def get_queryset(self):
        last_24_hours = datetime.datetime.today() - datetime.timedelta(1)
        events = Event.objects.none()
        for database in settings.EVENT_DATABASES:
            events |= Event.objects.using(database).filter(updated_at__gte=last_24_hours).exclude(code='OK')
        return events

    def get(self, request, format=None):
        queryset = self.get_queryset()
        serializer = EventSerializer(queryset, many=True)
        return Response(serializer.data)

【问题讨论】:

【参考方案1】:

你会想要使用itertools.chain

【讨论】:

你有例子吗? 您可以通过以下方式链接查询集:chain(queryset1, queryset2, ... , querysetN) @ChristianBouvier 是的,我可以这样链接它们。问题是序列化程序需要一个查询集对象,但链接后我有一个链对象。我收到错误'itertools.chain' object has no attribute 'model'。那么有没有办法将其转换回单个查询集?否则链接不是正确的解决方案....【参考方案2】:

如果您尝试合并相同模型的查询集,您可以使用| 运算符。

merged_queryset = queryset_1 | queryset_2

否则,您最好的朋友是itertools.chain(如上一个答案所述)。链的结果是一个链对象,您可以通过执行以下操作将其转换为列表:

merged_queryset = list(chain(queryset_1, queryset_2))

希望对您有所帮助!

【讨论】:

以上是关于是否可以将多个数据库中的多个 django 查询集合并到一个查询集中?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Django 中的 get_queryset 方法返回多个查询集对象或添加查询集结果

在 Django 中,正确地制作具有多个类别、多个标签和搜索的查询集?

我将如何将这些多个连接作为 Django 查询集进行?

具有多个字段的模型中的查询集(Django)

使用 Django 的 Case/When 查询集条件来设置多个值?

如何使用 StringAgg 或 ArrayAgg 连接多个子行中的一列来注释 django 查询集?