You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django ORM中无需循环生成以ref_id为键的字典结构

Django 无循环优化生成指定格式字典

问题背景

我在Django开发中想不使用循环来优化操作,生成特定格式的字典。

模型结构

class Test(BaseClass):
    id = models.UUIDField(unique=True)
    ref = models.ForeignKey(Ref)
    name = models.CharField(max_length=50)

数据表示例数据

+--------------------------------------+--------+----------------+
|                  id                  | ref_id |      name      |
+--------------------------------------+--------+----------------+
| 412dacb1-6451-4a1a-b3ac-09a30979b733 |      1 | test           |
| fa7abc8e-2070-40b6-af84-6a8d78676b89 |      2 | new_rule       |
| dd70a968-778c-4e45-9044-599effd243a6 |      3 | new_rule_test |
+--------------------------------------+--------+----------------+

目标字典格式

需要生成以ref_id为键,值为包含name和id的字典:

{
  1: {
    "name": "test",
    "id": UUID("412dacb1-6451-4a1a-b3ac-09a30979b733")
  },
  2: {
    "name": "new_rule",
    "id": UUID("fa7abc8e-2070-40b6-af84-6a8d78676b89")
  },
  3: {
    "name": "new_rule_test",
    "id": UUID("dd70a968-778c-4e45-9044-599effd243a6")
  }
}

现有可行方案(待优化)

尝试过annotate但未成功,目前只有以下代码能用,但数据量庞大时性能不足:

res_dict = Test.objects.filter(publisher_state='Published').values('ref', 'name', 'id')
final_dict = {row['ref']: {'name': row['name'], 'id': row['id']} for row in res_dict} 

优化方案

1. 使用in_bulk + 字典推导(平衡性能与可读性)

in_bulk可直接返回以指定字段为键的对象字典,避免中间values查询的额外内存开销:

# 按ref_id分组获取符合条件的Test对象
test_objects = Test.objects.filter(publisher_state='Published').in_bulk(field_name='ref')
# 转换为目标格式
final_dict = {
    ref_id: {'name': obj.name, 'id': obj.id}
    for ref_id, obj in test_objects.items()
}

优势:依托Django ORM的优化,减少内存占用,同时保持代码可读性,适合大部分大数据量场景。

2. 原生SQL直接查询(极致性能)

如果数据量极大,可跳过ORM对象实例化,直接操作原始查询结果:

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute("""
        SELECT ref_id, name, id 
        FROM yourapp_test 
        WHERE publisher_state = 'Published'
    """)
    # 用生成器表达式一次性构建字典,最小化内存占用
    final_dict = {
        row[0]: {'name': row[1], 'id': row[2]}
        for row in cursor.fetchall()
    }

优势:完全绕过ORM的对象处理逻辑,性能最优,但牺牲了ORM的兼容性和代码可读性,仅推荐超大数据量场景使用。

注意事项

  • 若存在多个Test对象对应同一个ref_id的情况,上述方案会自动保留最后一条查询结果(因字典键唯一),需提前通过distinct或SQL分组确保每个ref_id仅返回一条数据。
  • in_bulk要求指定的field_name字段无重复,或你能接受同键覆盖的逻辑。

内容的提问来源于stack exchange,提问作者Shubham Srivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 00:52:53