如何使用两个列表查询集过滤器?

Posted

技术标签:

【中文标题】如何使用两个列表查询集过滤器?【英文标题】:How to queryset filter with two lists? 【发布时间】:2021-10-12 02:49:04 【问题描述】:

我对 django 很陌生, 我有两个列表,我想过滤表中的值。我正在使用这个查询,但这给了我两个列表的联合,即 OR。我想要一些带有 AND 的东西,即以这种方式过滤值 retail_item_list = [100,120]city_id_list = [1,2] 输出应该基于这些组合 (100,1) (120,2)

val = list(KVIItem.objects.filter(Q(retail_item_id__in=retail_item_list, cms_city_id__in=city_id_list)).values("retail_item_id","cms_city_id","active","id").order_by('-id'))

编辑 1: 示例

retail_item_list = [10005681, 10005681, 10013955, 10013955, 10067631]
city_id_list = [959, 956, 959, 956, 2074]

使用这个查询

qfilter = Q(
            *[
                Q(cms_city_id=city,retail_item_id=retail)
                for city,retail in zip(city_id_list,retail_item_list)
            ],
            _connector=Q.OR
        )
        val = list(KVIItem.objects.filter(qfilter).values("retail_item_id","cms_city_id","active","id").order_by('-id'))

我得到了这些组合的结果: (10005681,956), (10013955,959), (10013955,956), (10067631,2074)

但目标是得到这些组合结果: (10005681,959), (10005681,956), (10013955,959), (10013955,956), (10067631,2074)

我的结果中缺少这个:(10005681,959) [第一个组合]

编辑 2:qfilter 打印

"(OR: (AND: ('cms_city_id', 959), ('retail_item_id', 10005681)), (AND: ('cms_city_id', 956), ('retail_item_id', 10005681)), (AND: ('cms_city_id', 959), ('retail_item_id', 10013955)), (AND: ('cms_city_id', 956), ('retail_item_id', 10013955)), (AND: ('cms_city_id', 2074), ('retail_item_id', 10067631)))"

编辑 3:此函数将返回更高 id 行。

def get_latest_kvi_item_among_same_items(val):
    dct = 
    for v in val:
        if v['cms_city_id'] not in dct:
            dct[v['cms_city_id']] = v
        else:
            d = dct[v['cms_city_id']]
            if v['id'] > d['id']:
                dct['cms_city_id'] = v
    valus = dct.values()
    a = list(valus)
    return a

【问题讨论】:

问题是如果我在本地运行它,它确实有效。你使用什么 Django 版本/数据库?可以分享数据库中的数据吗? codepile.net/pile/ydwxB3Qr 显示的这个数据,你能在这里查看链接吗? 当我使用给定数据创建记录时,我得到 31 条记录,这与您的代码堆代码片段中的项目数相同。 是的,因为记录有不同的 id。组合可以有不同的 id。我们必须获取最新的 id。如果 'retail_item_id': 10005681, 'cms_city_id': 956, 'active': True, 'id': 51609'retail_item_id': 10005681, 'cms_city_id': 956, 'active': True, 'id': 51610 那么我们将选择 id = 51610 因为它的 id 更大。 您的查询过滤器代码有效。我所做的是我首先从数据库 codepile.net/pile/ydwxB3Qr 中获取所有结果,我得到了结果。然后我在这里编写一些逻辑,只给出那些具有更高 id 的组合。例如:'retail_item_id':10005681,'cms_city_id':956,'active':真,'id':51609`'retail_item_id':10005681,'cms_city_id':956,'active':真,'id':51610 ` 如果这是我将得到的两个结果,那么之后我将遍历每个组合并返回具有更高 id 的组合。我更新了 EDIT 3 中的代码, 【参考方案1】:

您可以构造一个Q 对象,该对象将要求如果retail_item100,那么city_id 应该是1;或者如果retail_item120city_id2

我们可以这样做:

from django.db.models import Q

qfilter = Q(
    *[
        Q(retail_item_id=retail, cms_city_id=city)
        for retail, city in zip(retail_item_list, city_id_list)
    ],
    _connector=Q.OR
)

KVIItem.objects.filter(qfilter)

【讨论】:

感谢您的回答,但在这种情况下也可以吗?如果我有retail_id_list = [100,100,102]city_id_list = [1,2,3],我可以有重复的retail_ids,这意味着它可以存在于不同的城市。 @nihalsrivastava: 是的,在这种情况下它可以匹配city_id=1city_id=2 如果retail_id=100 是不是意味着它现在会像这样过滤,(100,1)(100,2)(102,3)这种方式? @nihalsrivastava:是的。 那太棒了,我要试试这个,10 分钟后告诉你。感谢您的帮助

以上是关于如何使用两个列表查询集过滤器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Django 中另一个查询集的结果过滤查询集?

如何使用同名的多个复选框自定义查询字符串?

如何使用动态过滤器制作 django 查询集?

如何使用 SQL 的“IN”等字段上的数组过滤 django 查询集?

如何使用 SQL 的“IN”等字段上的数组过滤 django 查询集?

如何通过计算过滤查询集?