第二章:模型(Models)与数据库 2.1 Django ORM 基础 Django ORM(Object-Relational Mapper,对象关系映射器)是 Django 框架的核心组件,为开发者提供了一套以 Python 对象方式操作关系型数据库的抽象层。它屏蔽了底层 SQL 差异,将数据库表映射为 Python 类、表记录映射为类实例、SQL 操作转换为方法调用,显著降低数据库交互复杂度,提升开发效率、代码可维护性与跨数据库可移植性。 本节系统讲解 Django ORM 的核心机制:从 ORM 设计理念出发,深入模型定义规范、字段类型与选项语义、迁移工作流原理,到 CRUD 操作实践、QuerySet 查询逻辑及链式调用范式,构建扎实的数据库操作能力基础。 2.1.
Django ORM(Object-Relational Mapper,对象关系映射器)是 Django 框架的核心组件,为开发者提供了一套以 Python 对象方式操作关系型数据库的抽象层。它屏蔽了底层 SQL 差异,将数据库表映射为 Python 类、表记录映射为类实例、SQL 操作转换为方法调用,显著降低数据库交互复杂度,提升开发效率、代码可维护性与跨数据库可移植性。
本节系统讲解 Django ORM 的核心机制:从 ORM 设计理念出发,深入模型定义规范、字段类型与选项语义、迁移工作流原理,到 CRUD 操作实践、QuerySet 查询逻辑及链式调用范式,构建扎实的数据库操作能力基础。
传统 Web 开发中,直接编写 SQL 语句操作数据库存在多重挑战:
ORM 通过建立“类→表、实例→行、方法→操作”的三层映射,将数据操作转化为面向对象范式。其核心价值在于:
filter()、exclude()、get() 等方法屏蔽 SQL 细节;在 Django 中,ORM 由 django.db.models 模块实现,其能力通过模型(Model)定义与 QuerySet 查询接口共同承载。
模型是 Django ORM 的基石,本质为继承 models.Model 的 Python 类,每个类对应数据库中一张表,每个属性对应一个字段。模型不仅定义数据结构,还承载验证规则、关系声明与业务逻辑。
# myapp/models.py from django.db import models from datetime import date class Book(models.Model): title = models.CharField(max_length=200, verbose_name="书名") author = models.CharField(max_length=100, verbose_name="作者") publication_date = models.DateField(verbose_name="出版日期") price = models.DecimalField( max_digits=5, decimal_places=2, verbose_name="定价", help_text="单位:人民币元" ) is_published = models.BooleanField( default=False, verbose_name="是否已出版" ) class Meta: verbose_name = "书籍" verbose_name_plural = "书籍" ordering = ["-publication_date"] def __str__(self): return self.title
| 组成部分 | 说明 |
|---|---|
| 字段类型 | CharField、DateField、DecimalField 等定义数据类型与约束;max_length、max_digits 等参数声明存储规格。 |
| 字段选项 | verbose_name 提升管理后台可读性;help_text 提供表单提示;default 设置默认值;null(数据库允许 NULL)、blank(表单允许空)分离数据层与表现层约束。 |
| Meta 类 | 声明模型元信息:verbose_name/verbose_name_plural 控制后台显示名称;ordering 定义默认排序;db_table 可自定义表名。 |
__str__ 方法 |
返回对象字符串表示,用于 Django Admin、Shell 及调试输出,提升可读性。 |
| 字段类型 | 适用场景 | 典型参数 |
|---|---|---|
AutoField |
主键(默认 id 字段) |
primary_key=True |
CharField |
短文本(标题、姓名) | max_length=200 |
TextField |
长文本(正文、描述) | — |
IntegerField / FloatField |
数值型数据 | — |
DecimalField |
精确数值(价格、金额) | max_digits=5, decimal_places=2 |
DateField / DateTimeField |
时间信息 | auto_now_add=True(创建时自动填充) |
BooleanField |
是/否状态 | default=False |
EmailField / URLField |
格式化文本 | 自动验证邮箱/URL 格式 |
ForeignKey |
一对多关系(如:图书←作者) | on_delete=models.CASCADE |
ManyToManyField |
多对多关系(如:图书↔标签) | related_name="books" |
OneToOneField |
一对一关系(如:用户↔个人资料) | on_delete=models.PROTECT |
模型定义需通过迁移同步至数据库,流程严格遵循以下三步:
settings.py 的 INSTALLED_APPS 中添加应用名(如 'myapp');python manage.py makemigrations,Django 检测模型变更并生成 .py 迁移脚本(如 0001_initial.py);python manage.py migrate,Django 执行迁移脚本,在数据库中创建/修改表结构。关键提示:迁移文件是数据库演进的版本记录,必须提交至代码仓库。生产环境严禁直接修改数据库结构,所有变更均需通过迁移管理。
Django ORM 将数据库操作封装为直观的 Python 方法,核心围绕 Model.objects 管理器(Manager)展开,支持完整的 Create、Read、Update、Delete 操作。
通过实例化模型类并调用 save() 方法插入数据:
from myapp.models import Book from datetime import date book = Book( title="Python 编程从入门到实践", author="Eric Matthes", publication_date=date(2019, 5, 1), price=59.90, is_published=True ) book.save() # 执行 INSERT,自动生成主键 ID print(f"书籍 '{book.title}' 已创建,ID:{book.id}")
QuerySet 是惰性求值的对象集合,是 Django 查询的核心载体。常见操作:
获取全部记录
all_books = Book.objects.all() # 返回 QuerySet,未执行查询 print(f"共 {all_books.count()} 本书") # count() 触发 SELECT COUNT for book in all_books: # 迭代触发 SELECT print(f"- {book.title}({book.author})")
条件过滤
# 标题含 "Python" 且价格 ≥ 60 的书籍 expensive_python_books = Book.objects.filter( title__contains="Python", price__gte=60 ).order_by("-price") # 2020 年后出版的书籍 recent_books = Book.objects.filter( publication_date__year__gt=2020 )
字段查找(Field Lookups)
| 查找符 | 含义 | 示例 |
|---|---|---|
__exact |
精确匹配(默认) | title__exact="Django" |
__iexact |
忽略大小写匹配 | title__iexact="django" |
__contains |
包含子串 | title__contains="Web" |
__icontains |
忽略大小写包含 | title__icontains="web" |
__startswith / __endswith |
开头/结尾匹配 | author__startswith="Eric" |
__gt / __gte / __lt / __lte |
数值比较 | price__gte=50 |
__in |
值在列表中 | author__in=["Eric", "Robert"] |
__isnull |
判断 NULL | publication_date__isnull=True |
__range |
闭区间范围 | publication_date__range=(d1, d2) |
获取单个对象
try: book = Book.objects.get(id=1) # 必须唯一,否则抛异常 print(f"ID=1 的书籍:{book.title}") except Book.DoesNotExist: print("未找到该书籍") except Book.MultipleObjectsReturned: print("查询返回多条记录")
排除条件
non_python_books = Book.objects.exclude(title__contains="Python")
单对象更新:获取实例 → 修改属性 → save()
try: book = Book.objects.get(title="Python 编程从入门到实践") book.price = 69.90 book.is_published = False book.save() # 生成 UPDATE 语句 except Book.DoesNotExist: pass
批量更新:直接操作 QuerySet,性能更优
updated = Book.objects.filter(author="Eric Matthes").update( is_published=False ) print(f"更新 {updated} 条记录")
单对象删除
try: book = Book.objects.get(title="Python 编程从入门到实践") title = book.title book.delete() # 生成 DELETE 语句 print(f"已删除:{title}") except Book.DoesNotExist: pass
批量删除
deleted, details = Book.objects.filter(price__gt=100).delete() print(f"删除 {deleted} 条记录")
QuerySet 支持方法链式调用,每个方法返回新 QuerySet,不修改原对象,支持组合复杂查询:
# 链式构建:Python 相关 + 价格 ≥ 60 + 按价格降序 + 仅取前 5 条 top_expensive_python = Book.objects \ .filter(title__icontains="python") \ .filter(price__gte=60) \ .order_by("-price") \ .values("title", "price", "publication_date") \ .distinct()[:5] for book in top_expensive_python: print(f"{book['title']} - ¥{book['price']}")
list()、count())时执行 SQL,避免无谓查询;filter()、exclude() 等均返回新 QuerySet,原 QuerySet 不变;filter().exclude().order_by();Django ORM 以模型为核心、QuerySet 为查询载体,构建了一套高效、安全、可维护的数据库操作范式。本节重点涵盖:
save()/delete() 作用于实例,update()/delete() 作用于 QuerySet,理解适用场景;__ 双下划线语法提供强大条件表达能力,覆盖 90%+ 查询需求。掌握上述内容,即具备使用 Django 构建健壮数据层的基础能力。后续章节将深入模型关系建模(ForeignKey/ManyToManyField)、聚合统计(aggregate()/annotate())、性能优化(select_related()/prefetch_related())及高级查询技巧,持续深化 ORM 应用深度。