Skip to content

Django ORM 详解

Django 框架以其“开箱即用”和“快速开发”的特性深受 Web 开发者喜爱,而其强大的对象关系映射(Object-Relational Mapping, ORM)系统是实现这一目标的关键组件之一。Django ORM 允许开发者使用 Python 代码来操作数据库,而无需直接编写复杂的 SQL 语句,极大地提高了开发效率和代码的可维护性。

理解对象关系映射 (ORM)

在探讨 Django ORM 之前,有必要先理解什么是 ORM。ORM 是一种编程技术,用于在关系型数据库和面向对象编程语言之间建立一座桥梁。简单来说,它允许开发者将数据库中的表映射为程序中的类(称为模型),将表中的行映射为类的实例(对象),将表中的字段映射为对象的属性。通过这种方式,开发者可以像操作普通 Python 对象一样来操作数据库记录,ORM 会在底层自动将这些对象操作转换为相应的 SQL 语句并执行。这就像一个翻译官,将开发者熟悉的面向对象语言“翻译”成数据库能理解的 SQL 语言,反之亦然,从而屏蔽了底层数据库的复杂性和差异性。

Django ORM 的核心组件

Django ORM 主要由几个关键部分组成,它们协同工作,构成了与数据库交互的基础。

模型 (Models)

模型是 Django ORM 的核心,它定义了应用程序的数据结构。每个模型通常对应数据库中的一张表。开发者通过继承 django.db.models.Model 类来定义模型,并在类中定义字段(Fields)来表示表的列。每个字段都是 models.Field 的一个实例(例如 CharFieldIntegerFieldDateTimeField 等),它不仅定义了数据库列的类型,还包含了数据验证、默认值、表单生成等多种功能。

例如,可以定义一个简单的 Book 模型来表示书籍信息:

python
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)
    publication_date = models.DateField(null=True, blank=True)
    isbn = models.CharField(max_length=13, unique=True)

    def __str__(self):
        return self.title

在这个例子中,Book 类映射到数据库中的一张表,titleauthorpublication_dateisbn 属性分别对应表中的列。__str__ 方法定义了模型实例的字符串表示形式,方便在管理后台或调试时查看。

管理器 (Managers)

每个 Django 模型至少有一个管理器(Manager),它是模型与数据库进行交互的主要接口。默认情况下,每个模型都有一个名为 objects 的管理器(models.Manager 的实例)。开发者通过管理器来执行数据库查询操作,例如获取所有记录、过滤记录等。

例如,要获取所有的 Book 对象,可以使用 Book.objects.all()

开发者也可以定义自定义管理器,以添加额外的查询方法或修改默认的查询集行为,从而封装常用的数据访问逻辑。

查询集 (QuerySets)

查询集(QuerySet)代表了从数据库中检索到的一组对象集合。当通过管理器调用查询方法(如 all()filter()exclude())时,返回的就是一个查询集。查询集具有“惰性求值”(Lazy Evaluation)的特性,这意味着创建查询集本身并不会立即执行数据库查询。只有在需要访问查询集中的数据时(例如迭代、切片、调用 len() 或显式转换列表等),Django ORM 才会真正执行 SQL 查询并将结果加载到内存中。这种惰性机制有助于提高性能,避免不必要的数据库访问。

基本数据库操作 (CRUD)

掌握 Django ORM 的基本数据库增删改查(CRUD)操作是进行 Django 开发的基础。

创建 (Create) 数据

创建新的数据库记录通常有两种方式。第一种是创建模型实例,设置属性后调用 save() 方法:

python
# 方法一:创建实例并保存
new_book = Book(title="深入理解计算机系统", author="Randal E. Bryant", isbn="9787111213409")
new_book.save()

第二种是使用管理器的 create() 方法,它会一步完成实例创建和保存:

python
# 方法二:使用管理器的 create 方法
another_book = Book.objects.create(title="代码整洁之道", author="Robert C. Martin", isbn="9787115216109")

查询 (Read) 数据

Django ORM 提供了丰富的查询接口。

获取所有记录使用 all() 方法:

python
all_books = Book.objects.all() # 返回一个包含所有 Book 对象的 QuerySet

根据条件过滤记录使用 filter()exclude() 方法。filter() 返回满足条件的对象,exclude() 返回不满足条件的对象:

python
# 获取所有 Randal E. Bryant 写的书
bryant_books = Book.objects.filter(author="Randal E. Bryant")

# 获取除了 Randal E. Bryant 写的书之外的所有书
other_books = Book.objects.exclude(author="Randal E. Bryant")

获取单个特定记录使用 get() 方法。需要注意的是,get() 期望查询结果是唯一的。如果查询没有找到任何对象,会引发 Model.DoesNotExist 异常;如果找到多个对象,会引发 Model.MultipleObjectsReturned 异常。因此,get() 通常用于基于主键或唯一约束字段的查询。

python
try:
    specific_book = Book.objects.get(isbn="9787111213409")
except Book.DoesNotExist:
    print("书籍不存在")
except Book.MultipleObjectsReturned:
    print("找到多本相同 ISBN 的书籍,数据可能存在问题")

对结果进行排序使用 order_by() 方法:

python
# 按出版日期升序排序
books_sorted_by_date = Book.objects.order_by('publication_date')
# 按出版日期降序排序
books_sorted_by_date_desc = Book.objects.order_by('-publication_date')

查询集还支持 Python 的切片语法,用于限制返回结果的数量:

python
# 获取前 5 本书
first_five_books = Book.objects.all()[:5]
# 获取第 6 到第 10 本书
next_five_books = Book.objects.all()[5:10]

更新 (Update) 数据

更新数据同样有两种常见方式。第一种是先获取对象,修改其属性,然后调用 save() 方法:

python
book_to_update = Book.objects.get(isbn="9787111213409")
book_to_update.title = "深入理解计算机系统(原书第3版)"
book_to_update.save()

第二种是使用查询集的 update() 方法进行批量更新,这种方式更高效,因为它直接在数据库层面执行 SQL UPDATE 语句,不会加载对象到内存,也不会调用模型的 save() 方法或触发相关信号:

python
# 将所有 Randal E. Bryant 写的书的作者名更新(示例,实际意义不大)
Book.objects.filter(author="Randal E. Bryant").update(author="R. E. Bryant")

删除 (Delete) 数据

删除数据可以针对单个对象,也可以批量进行。删除单个对象需要先获取该对象,然后调用其 delete() 方法:

python
book_to_delete = Book.objects.get(isbn="9787115216109")
book_to_delete.delete()

批量删除则可以直接在查询集上调用 delete() 方法:

python
# 删除所有作者为 "Unknown Author" 的书籍
Book.objects.filter(author="Unknown Author").delete()

Django ORM 的优势

使用 Django ORM 带来了诸多好处。首先是显著提升了开发效率,开发者可以用熟悉的 Python 语法与数据库交互,减少了编写和调试 SQL 的时间。其次,它提供了良好的数据库无关性,理论上更换数据库后端(如从 SQLite 切换到 PostgreSQL 或 MySQL)只需修改配置文件,而无需大量修改数据访问代码,尽管在实践中可能需要注意一些数据库特定的细节。再者,Django ORM 内置了对 SQL 注入等常见安全威胁的防护机制,提高了应用的安全性。最后,基于模型的代码结构清晰,使得代码更易读、更易维护

小结

Django ORM 是 Django 框架中一个强大而优雅的部分,它通过对象关系映射技术简化了数据库操作,让开发者能够聚焦于业务逻辑的实现。理解其核心组件(模型、管理器、查询集)和掌握基本的 CRUD 操作是高效使用 Django 进行 Web 开发的基础。虽然 ORM 屏蔽了许多底层细节,但在处理复杂查询或性能优化时,了解其生成的 SQL 语句仍然是有益的。总而言之,熟练运用 Django ORM 将极大地提升开发体验和项目质量。

参考资料