Django orm详解--工作流程

发布于:2025-05-27 ⋅ 阅读:(15) ⋅ 点赞:(0)

Django ORM 的完整工作流程涵盖 模型构建查询执行数据库交互结果映射 四大阶段。以下是详细解析,包含了你之前提到的 Model 构建阶段:

一、模型构建阶段(Model Construction)

1. 元类解析模型结构
  • 核心元类django.db.models.base.ModelBase
  • 关键步骤
    1. 解析字段:遍历模型类属性,提取 Field 子类(如 CharFieldForeignKey)。
    2. 生成元数据:创建 Options 类,存储 db_tableindexes 等元信息。
    3. 建立关系:处理 ForeignKeyManyToManyField,生成反向关联描述。
    4. 注册模型:将模型类注册到 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
  • 关键步骤
    1. 解析查询树:将 WhereNode 转换为 SQL WHERE 子句。
    2. 处理 JOIN:自动生成关联查询的 JOIN 语句。
    3. 参数化查询:动态值使用占位符(如 %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
  • 关键步骤
    1. 将数据库行数据(元组)映射到模型字段。
    2. 处理关联字段:
      • 立即加载:通过 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                    │  解析结果集                  │
                  │                              │  └─────────────────────────> │  ↓                          │
                  │                              │                              │  实例化模型对象               │
                  │                              │                              │  ↓                          │
                  │                              │                              │  应用缓存策略                 │
                  │                              │                              │  ↓                          │
                  │                              │                              │  返回结果集                  │
                  │                              │                              │                              │

六、关键优化点

  1. 减少查询次数

    • 使用 select_related() 处理一对一/外键关联(JOIN 查询)。
    • 使用 prefetch_related() 处理多对多/反向关联(子查询)。
  2. 避免全表扫描

    • 通过 Meta.indexes 为高频查询字段添加索引。
    • 使用 filter() 代替 all() 缩小结果集。
  3. 优化数据提取

    • 使用 values()/values_list() 直接返回字典/元组。
    • 使用 only()/defer() 只加载需要的字段。

网站公告

今日签到

点亮在社区的每一天
去签到