基于公共字段组合两个 Django 查询集
Combine two Django Querysets based on common field
我有两个查询集(实际上是字典列表),例如:
q1 = M1.objects.filter(id=pk).values('p_id', 'q1_quantity')
# q1: <Queryset[{'p_id': 2, 'q1_quantity': 4}, {'p_id': 3, 'q1_quantity': 5}]>
q2 = M2.objects.filter(p_id__in=[q1[x]['p_id'] for x in range(len(q1))]).values('p_id', 'q2_quantity')
# q2: <Queryset[{'p_id': 2, 'q2_quantity': 2}, {'p_id': 2, 'q2_quantity': 5}, {'p_id': 3, 'q2_quantity': 1}, {'p_id': 3, 'q2_quantity': 7}]>
q1 有不同的 key:value 对,而 q2 有重复的键。
1) 我想将 q2 的所有值按 common p_id 求和,这样 q2 就变成:
# q2: <Queryset[{'p_id': 2, 'q2_quantity': 7}, {'p_id': 3, 'q2_quantity': 8}]>
2) 然后,根据共同的p_id,将q1和q2合并为q3,如:
q3 = ?
# q3: <Queryset[{'p_id': 2, 'q1_quantity': 4, 'q2_quantity': 7}, {'p_id': 3, 'q1_quantity': 5, 'q2_quantity': 8}]>
我调查了 union()。但不知道如何对查询集 (q2) 求和,然后将其与 q1 合并。
有人可以帮我吗?
问题在于您正在实施效率低下的模型,拥有 2 个具有重复字段的独立模型将迫使您进行 2 次查询。您可能需要考虑将它们全部放在一个模型中,或者 M2
模型扩展 M1
.
models.py
class M(models.Model):
p_id = #Your Field...
q1_quantity = #Your Field...
q2_quantity = #Your Field...
然后在你的 views.py
q = M.objects.filter(id=pk).values('p_id', 'q1_quantity', 'q2_quantity')
潜在问题: 在您发布的代码中,注释部分显示了超过 1 个对象的查询集,并且 pk
作为主键应该是唯一的,因此应该return 一个独特的对象查询集。
1) 我想将 q2 的所有值按 common p_id 求和,这样 q2 就变成:
# q2: <Queryset[{'p_id': 2, 'q2_quantity': 7}, {'p_id': 3, 'q2_quantity': 8}]>
二手 itertools.combinations:
from itertools import combinations
compare = []
for a, b in combinations(q2, 2):
if a['p_id'] == b ['p_id']:
a['q2_quantity'] += b['q2_quantity']
if len(compare) <= 0:
compare.append(a)
else:
[compare[d]['q2_quantity'] for d in range(len(compare)) if a['p_id'] == compare[d]['p_id']]
else:
if len(compare) <= 0:
compare.append(a)
compare.append(b)
else:
if any([a['p_id'] == compare[d]['p_id'] for d in range(len(compare))]):
pass
else:
compare.append(a)
if any([b['p_id'] == compare[d]['p_id'] for d in range(len(compare))]):
pass
else:
compare.append(b)
2) 然后,根据共同的p_id,将q1和q2合并为q3,如:
q3 = ?
# q3: <Queryset[{'p_id': 2, 'q1_quantity': 4, 'q2_quantity': 7}, {'p_id': 3, 'q1_quantity': 5, 'q2_quantity': 8}]>
根据这个 SO post:
from collections import defaultdict
from itertools import chain
collector = defaultdict(dict)
for collectible in chain(cp, compare):
collector[collectible['p_id']].update(collectible.items())
products = list(collector.values())
我有两个查询集(实际上是字典列表),例如:
q1 = M1.objects.filter(id=pk).values('p_id', 'q1_quantity')
# q1: <Queryset[{'p_id': 2, 'q1_quantity': 4}, {'p_id': 3, 'q1_quantity': 5}]>
q2 = M2.objects.filter(p_id__in=[q1[x]['p_id'] for x in range(len(q1))]).values('p_id', 'q2_quantity')
# q2: <Queryset[{'p_id': 2, 'q2_quantity': 2}, {'p_id': 2, 'q2_quantity': 5}, {'p_id': 3, 'q2_quantity': 1}, {'p_id': 3, 'q2_quantity': 7}]>
q1 有不同的 key:value 对,而 q2 有重复的键。
1) 我想将 q2 的所有值按 common p_id 求和,这样 q2 就变成:
# q2: <Queryset[{'p_id': 2, 'q2_quantity': 7}, {'p_id': 3, 'q2_quantity': 8}]>
2) 然后,根据共同的p_id,将q1和q2合并为q3,如:
q3 = ?
# q3: <Queryset[{'p_id': 2, 'q1_quantity': 4, 'q2_quantity': 7}, {'p_id': 3, 'q1_quantity': 5, 'q2_quantity': 8}]>
我调查了 union()。但不知道如何对查询集 (q2) 求和,然后将其与 q1 合并。
有人可以帮我吗?
问题在于您正在实施效率低下的模型,拥有 2 个具有重复字段的独立模型将迫使您进行 2 次查询。您可能需要考虑将它们全部放在一个模型中,或者 M2
模型扩展 M1
.
models.py
class M(models.Model):
p_id = #Your Field...
q1_quantity = #Your Field...
q2_quantity = #Your Field...
然后在你的 views.py
q = M.objects.filter(id=pk).values('p_id', 'q1_quantity', 'q2_quantity')
潜在问题: 在您发布的代码中,注释部分显示了超过 1 个对象的查询集,并且 pk
作为主键应该是唯一的,因此应该return 一个独特的对象查询集。
1) 我想将 q2 的所有值按 common p_id 求和,这样 q2 就变成:
# q2: <Queryset[{'p_id': 2, 'q2_quantity': 7}, {'p_id': 3, 'q2_quantity': 8}]>
二手 itertools.combinations:
from itertools import combinations
compare = []
for a, b in combinations(q2, 2):
if a['p_id'] == b ['p_id']:
a['q2_quantity'] += b['q2_quantity']
if len(compare) <= 0:
compare.append(a)
else:
[compare[d]['q2_quantity'] for d in range(len(compare)) if a['p_id'] == compare[d]['p_id']]
else:
if len(compare) <= 0:
compare.append(a)
compare.append(b)
else:
if any([a['p_id'] == compare[d]['p_id'] for d in range(len(compare))]):
pass
else:
compare.append(a)
if any([b['p_id'] == compare[d]['p_id'] for d in range(len(compare))]):
pass
else:
compare.append(b)
2) 然后,根据共同的p_id,将q1和q2合并为q3,如:
q3 = ?
# q3: <Queryset[{'p_id': 2, 'q1_quantity': 4, 'q2_quantity': 7}, {'p_id': 3, 'q1_quantity': 5, 'q2_quantity': 8}]>
根据这个 SO post:
from collections import defaultdict
from itertools import chain
collector = defaultdict(dict)
for collectible in chain(cp, compare):
collector[collectible['p_id']].update(collectible.items())
products = list(collector.values())