如何在Django中关联不同模型的QuerySet生成含新增字段的新查询集
解决方案
方案1:Python内存合并(适合小数据量场景)
逻辑简单易维护,适合查询范围内数据量在万级以下的场景,自动兼容某日期仅存在单渠道销售数据的情况:
# 把两个查询集转为以销售日期为key的字典 a_map = {item["sales_date"]: item["store_sales"] for item in querysetA} b_map = {item["sales_date"]: item["online_sales"] for item in querysetB} # 取两个查询集的所有日期,去重后排序 all_sales_dates = sorted(set(a_map.keys()).union(b_map.keys())) # 构造最终的合并结果 querysetC = [] for index, sales_date in enumerate(all_sales_dates, 1): store_sales = a_map.get(sales_date, 0.00) online_sales = b_map.get(sales_date, 0.00) querysetC.append({ "id": index, "sales_date": sales_date, "store_sales": store_sales, "online_sales": online_sales, "combine_sales": store_sales + online_sales })
方案2:ORM数据库层查询(适合大数据量场景)
直接在数据库层面完成关联聚合,内存开销更低,适合数据量较大的场景,需要先引入ORM工具类:
from django.db.models import Sum, Subquery, OuterRef, FloatField # 构造线上销售额的子查询 online_subquery = online_shop.objects.filter( sales_date=OuterRef("sales_date"), sales_date__range=(fromdate, todate) ).values("sales_date").annotate( online_sales=Sum("sales_income") ).values("online_sales") # 主查询关联子查询,直接生成合并结果 querysetC = store_shop.objects.filter( sales_date__range=(fromdate, todate) ).values("sales_date").annotate( store_sales=Sum("sales_income"), online_sales=Subquery(online_subquery, output_field=FloatField()), combine_sales=Sum("sales_income") + Subquery(online_subquery, output_field=FloatField()) ).order_by("sales_date")
如果存在某日期仅在线上渠道有销售数据的情况,可先生成覆盖整个查询范围的日期序列作为主表,再分别关联两个渠道的聚合结果即可。
你之前尝试的union()和itertools.chain无法达成效果的原因是,二者都是对查询结果做行级拼接,而非按公共字段sales_date做列级合并,不符合你的需求场景。
内容的提问来源于stack exchange,提问作者James Ho Hon Yan
相关产品推荐
相关产品推荐

