【问题标题】:Combine two Django Querysets based on common field基于公共字段组合两个 Django 查询集
【发布时间】:2020-08-31 06:50:22
【问题描述】:

我有两个查询集(实际上是字典列表),例如:

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 有不同的键值对,而 q2 有重复的键。

1) 我想用公共 p_id 将 q2 的所有值相加,使得 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 合并。

有人可以帮帮我吗?

【问题讨论】:

    标签: django python-3.x orm django-orm


    【解决方案1】:

    问题在于您实施的模型效率低下,拥有 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 作为主键应该是唯一的,因此应该返回一个唯一的对象查询集。

    【讨论】:

    • M1 和 M2 是两个不同应用程序的模型。我要求它们分开,但同时需要将它们的数量显示在一起。 M1 基本上是一个组件模型,M2 是过程模型。 p_id 基本上是两个模型共有的“产品”字段(FK 字段)。我在一个视图中同时需要组件数量和工艺数量。
    【解决方案2】:

    1) 我想用公共 p_id 将 q2 的所有值相加,使得 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())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-30
      • 2023-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多