在 Django 的 MTV 架构中,M (Model) 层不仅负责定义数据结构,还通过 ORM (Object-Relational Mapping) 技术封装了所有的数据库操作。Django ORM 是一个强大的 Python 数据库抽象层,它允许我们使用面向对象的方式去操作关系型数据库,而几乎不需要编写 SQL 语句。
本节将基于 Django 的内部类结构,深入剖析 ORM 的核心组件:元类、模型、管理器和查询集。
【uml图例】重点突出在实际开发中会直接使用和继承的核心类

1. ORM 的基石:元类 ModelBase
在 Python 中,普通类是由 type 创建的。但在 Django 中,所有的模型类(如 class User(models.Model))都由一个特殊的元类 ModelBase 负责创建。这是 Django ORM 能够"魔法般"工作的根本原因。
1.1 为什么需要元类?
当你定义一个模型时:
class User(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
Python 解释器在执行到 class User 时,不仅执行了类体内的代码,还会调用元类的 __new__ 和 __call__ 方法。Django 利用这个时机,做了三件至关重要的事情:
- 字段映射 :扫描类属性,将
CharField、IntegerField等字段对象提取出来,放入_meta.fields列表中,同时从类属性中删除它们(这样实例访问user.name时就不会访问到字段对象本身,而是访问到数据库中的值)。 - 元数据封装 :读取内部类
class Meta,将其配置(如db_table,ordering)封装到一个Options对象中,并赋值给User._meta。 - 添加管理器 :如果模型中没有定义
objects属性,元类会自动添加一个默认的Manager实例。
架构图解 :
ModelBase 继承自 Python 的 type。
Model 使用 ModelBase 作为其元类。
1.2 Options 对象:模型的元数据中心
每个模型类都有一个 _meta 属性,它是一个 Options 实例。这个对象存储了模型的所有元数据,但不包含具体的数据值。
- 核心属性 :
app_label:应用名(如 'users')。model_name:模型名(如 'user')。db_table:数据库表名。fields:包含所有字段对象的列表。
- 调试用途 :当你需要动态获取模型信息(例如在写通用组件时),
Model._meta是最权威的来源。
2. 数据库行为的入口:Manager 与 QuerySet
Django ORM 最著名的特点是其"链式调用",如 User.objects.filter(active=True).order_by('name')。这背后是 Manager 和 QuerySet 的精密配合。
2.1 Manager:模型的接口
Model.objects 是一个 Manager 类的实例。它是模型进行数据库操作的入口。
- 职责 :
Manager本身通常不直接执行查询,而是返回一个QuerySet对象。 - 自定义管理器 :你可以在模型中自定义管理器,以修改初始查询集或添加自定义方法(如
User.active_users.all())。
2.2 QuerySet:惰性查询的载体
QuerySet 是 Django ORM 的核心。它代表了数据库中的一组记录,但直到真正需要数据时(如迭代、序列化、len()),才会访问数据库。这就是"惰性求值"。
- 链式调用原理 :
- 当你调用
User.objects.filter(age=18)时,它返回一个新的QuerySet,并在内部复制了 SQL 查询条件(WHERE age = 18)。 - 当你接着调用
.order_by('name')时,它再次返回一个新的QuerySet,并追加排序条件(ORDER BY name)。 - 整个过程中,没有发生任何数据库访问。
- 当你调用
- SQL 构建 :
QuerySet内部持有一个Query对象,负责将 Python 条件逐步转换为 SQL AST(抽象语法树)。- 当触发求值时,
Query对象生成最终的 SQL 语句,发送给数据库驱动。
架构图解 :
Manager 持有对 Model 的引用。
Manager 创建并返回 QuerySet。
QuerySet 内部包含查询逻辑。
3. 字段系统:Python 类型与数据库类型的桥梁
模型中的每个属性(如 name = CharField(...))都是 Field 类的实例。字段类负责定义列的类型、约束以及 Python 值与数据库值之间的转换。
3.1 字段继承体系
Django 提供了丰富的字段类型,都继承自基类 Field。
- 基础类型 :
- CharField:映射为
VARCHAR。 - IntegerField:映射为
INTEGER。 - DateTimeField:映射为
TIMESTAMP或DATETIME。
- CharField:映射为
- 关系类型 :
- ForeignKey:映射为外键,建立多对一关系。
- ManyToManyField:映射为中间表,建立多对多关系。
- OneToOneField:映射为唯一外键,建立一对一关系。
3.2 字段的作用
- 定义 Schema :通过
makemigrations和migrate命令,Django 读取字段定义生成CREATE TABLESQL。 - 数据验证 :在
save()之前,字段会验证数据类型(如IntegerField不接受字符串)。 - 类型转换 :从数据库取出原始数据(如字符串 '2023-01-01')后,字段将其转换为 Python 对象(如
datetime.datetime对象)。
4. 完整的查询生命周期
让我们通过一个简单的例子,串联上述所有组件:
# 代码:获取名字为 'Alice' 的用户
user = User.objects.get(name='Alice')
内部执行流程:
- 入口 :
User.objects访问Manager。 - 构建查询 :
Manager.get()方法内部调用QuerySet.filter(name='Alice')。 - 链式处理 :
QuerySet将条件添加到内部状态中。 - 触发执行 :
get()是一个立即执行方法,它强制QuerySet去数据库查询。 - SQL 生成 :
QuerySet内部的Query对象生成 SQL:SELECT * FROM user WHERE name = 'Alice'。 - 数据库交互 :通过
django.db.connection(由settings.DATABASES配置)发送 SQL 到数据库。 - 结果映射 :
- 获取原始结果行。
- Model 实例化一个对象。
- 利用 Options 和 Field 定义,将每一列的值赋给对象的属性。
- 返回 :返回填充好数据的
User实例。
5. 总结
Django ORM 是一个精巧设计的系统,它通过以下机制实现了 Python 对象与关系数据库的无缝对接:
- 元类 (
ModelBase) :在类创建时介入,修改类定义,提取字段信息到_meta,并添加管理器。 - 管理器 (
Manager):作为数据库操作的 API 接口,管理查询集的创建。 - 查询集 (
QuerySet):实现了惰性求值和链式调用,负责 SQL 的构建和执行。 - 字段 (
Field):定义了数据结构、验证规则以及 Python 与数据库之间的类型转换。