如何使用两个列表查询集过滤器?
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_item
是100
,那么city_id
应该是1
;或者如果retail_item
是120
而city_id
是2
。
我们可以这样做:
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=1
或city_id=2
如果retail_id=100
。
是不是意味着它现在会像这样过滤,(100,1)
,(100,2)
,(102,3)
这种方式?
@nihalsrivastava:是的。
那太棒了,我要试试这个,10 分钟后告诉你。感谢您的帮助以上是关于如何使用两个列表查询集过滤器?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SQL 的“IN”等字段上的数组过滤 django 查询集?