Django orm详解--工作流程
Django ORM 的完整工作流程涵盖 模型构建、查询执行、数据库交互 和 结果映射 四大阶段。以下是详细解析,包含了你之前提到的 Model 构建阶段:
一、模型构建阶段(Model Construction)
1. 元类解析模型结构
- 核心元类:
django.db.models.base.ModelBase - 关键步骤:
- 解析字段:遍历模型类属性,提取
Field子类(如CharField、ForeignKey)。 - 生成元数据:创建
Options类,存储db_table、indexes等元信息。 - 建立关系:处理
ForeignKey、ManyToManyField,生成反向关联描述。 - 注册模型:将模型类注册到
django.apps.apps注册表。
- 解析字段:遍历模型类属性,提取
2. 字段与数据库类型映射
- 示例映射:
class Book(models.Model):title = models.CharField(max_length=100) # VARCHAR(100)price = models.DecimalField(max_digits=5, decimal_places=2) # DECIMAL(5,2)published_date = models.DateField() # DATE
3. 验证模型完整性
- Django 启动时(或执行
makemigrations)验证:- 字段参数合法性(如
max_length必须为整数)。 - 关联关系一致性(如确保关联模型存在)。
- 字段参数合法性(如
二、查询执行阶段(Query Execution)
1. 查询集创建与链式操作
- 核心类:
django.db.models.query.QuerySet - 惰性特性:
# 未执行 SQL queryset = Book.objects.filter(author="Doubao").order_by("-price")# 表达式树结构: # Query { # model: Book, # where: [AND, =(author, "Doubao")], # order_by: ["-price"] # }
2. 查询表达式树构建
- 核心组件:
WhereNode:存储过滤条件。OrderBy:存储排序规则。Annotation:存储聚合逻辑(如Count('reviews'))。
三、数据库交互阶段(Database Interaction)
1. SQL 生成与编译
- 核心类:
django.db.backends.*.compiler.SQLCompiler - 关键步骤:
- 解析查询树:将
WhereNode转换为 SQLWHERE子句。 - 处理 JOIN:自动生成关联查询的
JOIN语句。 - 参数化查询:动态值使用占位符(如
%s)。
- 解析查询树:将
# Python 查询
books = Book.objects.filter(author="Doubao", price__gt=50)# 生成的 SQL(PostgreSQL 示例)
SELECT "books"."id", "books"."title", "books"."author", "books"."price"
FROM "books"
WHERE ("books"."author" = %s AND "books"."price" > %s);# 参数:['Doubao', 50.0]
2. 数据库连接与执行
- 核心类:
django.db.backends.*.base.DatabaseWrapper - 连接管理:
- 默认每次请求创建新连接,请求结束后关闭。
- 支持第三方连接池(如
django - db - connection - pool)。
3. 事务处理
- 自动提交模式:默认每条 SQL 作为独立事务。
- 显式事务:通过
@transaction.atomic管理事务边界。
四、结果映射阶段(Result Mapping)
1. 数据库结果解析
- 核心类:
django.db.models.loading.ModelLoader - 关键步骤:
- 将数据库行数据(元组)映射到模型字段。
- 处理关联字段:
- 立即加载:通过
select_related()执行 JOIN 查询。 - 延迟加载:通过
prefetch_related()执行子查询。
- 立即加载:通过
2. 对象实例化与缓存
- 实例化流程:
# 数据库返回:(1, "Python Crash Course", "Doubao", 99.99) # 转换为模型对象: book = Book(id=1, title="Python Crash Course", author="Doubao", price=99.99) - 缓存机制:
QuerySet首次求值后缓存结果(_result_cache)。- 重复访问同一
QuerySet直接返回缓存。
五、完整工作流程图解
1. 模型构建阶段 2. 查询执行阶段 3. 数据库交互阶段 4. 结果映射阶段
─────────────────┐ ────────────────────┐ ────────────────────┐ ───────────────────│ │ │ │
定义模型类 │ │ │ │
↓ │ │ │ │
元类解析字段 │ │ │ │
↓ │ │ │ │
生成元数据 │ │ │ │
↓ │ │ │ │
注册模型 │ 创建查询集 │ │ ││ ↓ │ │ ││ 添加过滤/排序条件 │ │ ││ ↓ │ │ ││ 触发 SQL 执行 │ 生成 SQL 语句 │ │├──────────────────────────> │ ↓ │ ││ │ 获取数据库连接 │ ││ │ ↓ │ ││ │ 执行 SQL │ 解析结果集 ││ │ └─────────────────────────> │ ↓ ││ │ │ 实例化模型对象 ││ │ │ ↓ ││ │ │ 应用缓存策略 ││ │ │ ↓ ││ │ │ 返回结果集 ││ │ │ │
六、关键优化点
-
减少查询次数:
- 使用
select_related()处理一对一/外键关联(JOIN 查询)。 - 使用
prefetch_related()处理多对多/反向关联(子查询)。
- 使用
-
避免全表扫描:
- 通过
Meta.indexes为高频查询字段添加索引。 - 使用
filter()代替all()缩小结果集。
- 通过
-
优化数据提取:
- 使用
values()/values_list()直接返回字典/元组。 - 使用
only()/defer()只加载需要的字段。
- 使用
