在 Django 中,ORM(Object Relational Mapping,对象关系映射) 是框架的核心之一。它允许你使用 Python 代码来操作数据库,而无需编写原始 SQL 语句。Django ORM 不仅简化了数据库操作,还提升了代码的可读性、可维护性和安全性。
本文将带你从基础到进阶,全面了解 Django ORM 的使用方式,包括模型定义、字段类型、查询操作、聚合函数、关系映射、性能优化等内容。
一、什么是 Django ORM?
ORM 是一种编程技术,它将数据库中的表映射为 Python 类,表中的行映射为类的实例,字段映射为类的属性。
在 Django 中:
- 每个模型(Model)对应数据库中的一张表;
- 每个模型实例对应表中的一条记录;
- 每个模型类的属性对应表中的字段。
优点:
- 跨数据库兼容:支持多种数据库(PostgreSQL、MySQL、SQLite、Oracle);
- 避免 SQL 注入:ORM 会自动处理参数化查询;
- 提高开发效率:用 Python 代码操作数据库,无需写 SQL;
- 结构清晰:模型定义清晰,易于维护。
二、定义模型(Model)
示例:定义一个博客文章模型
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(Author, on_delete=models.CASCADE)
published = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
常见字段类型:
字段类型 |
说明 |
|
字符串字段,必须指定 |
|
长文本字段 |
|
整数 |
|
布尔值(True/False) |
|
时间日期字段, 自动设置创建时间, 自动更新时间 |
|
邮箱字段,自动验证格式 |
|
外键,用于建立一对多关系 |
|
多对多关系 |
|
一对一关系 |
三、字段选项(Field Options)
字段可以设置各种选项,控制其行为:
选项 |
说明 |
|
允许该字段为 NULL(数据库层面) |
|
表单验证时允许为空(Django 层面) |
|
设置默认值 |
|
字段值必须唯一 |
|
字段的可读名称,用于管理界面 |
|
表单帮助信息 |
|
限制字段的取值范围,如性别字段 |
示例:
GENDER_CHOICES = (
('M', '男'),
('F', '女'),
)
class Profile(models.Model):
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
四、模型关系
Django ORM 支持三种主要的关系类型:
1. 一对一(OneToOneField)
class User(models.Model):
username = models.CharField(max_length=100)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField()
2. 一对多(ForeignKey)
class Post(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
3. 多对多(ManyToManyField)
class Tag(models.Model):
name = models.CharField(max_length=30)
class Post(models.Model):
tags = models.ManyToManyField(Tag)
五、查询操作(QuerySet)
Django ORM 提供了强大的查询 API,可以使用链式调用构建复杂的查询。
1. 基本查询
Post.objects.all() # 获取所有文章
Post.objects.get(id=1) # 获取主键为 1 的文章(不存在会抛异常)
Post.objects.filter(title='Django') # 过滤标题为 Django 的文章
Post.objects.exclude(title='SQL') # 排除标题为 SQL 的文章
2. 查询条件(Field Lookups)
条件 |
示例 |
说明 |
|
|
精确匹配 |
|
|
忽略大小写匹配 |
|
|
包含字符串 |
|
|
忽略大小写包含 |
|
|
大于 |
|
|
大于等于 |
|
|
小于 |
|
|
小于等于 |
|
|
在某个列表中 |
|
|
判断是否为 NULL |
3. 排序与切片
Post.objects.order_by('title') # 按标题升序
Post.objects.order_by('-title') # 按标题降序
Post.objects.all()[:5] # 取前5条记录
4. 聚合查询(Aggregate)
from django.db.models import Count, Avg, Max, Min, Sum
Post.objects.aggregate(Avg('id')) # 平均值
Post.objects.aggregate(Max('id')) # 最大值
Post.objects.annotate(count=Count('author')) # 按作者统计文章数量
六、Meta 元类配置
通过 class Meta
可以配置模型的元信息:
class Post(models.Model):
title = models.CharField(max_length=200)
class Meta:
db_table = 'blog_posts' # 自定义表名
ordering = ['-created_at'] # 默认排序
verbose_name = '博客文章'
verbose_name_plural = '博客文章列表'
七、模型方法
你可以在模型中定义自定义方法,用于封装业务逻辑:
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def full_name(self):
return f"{self.first_name} {self.last_name}"
八、迁移(Migrations)
每次修改模型后,需要运行迁移命令更新数据库结构:
# 生成迁移文件
python manage.py makemigrations
# 应用迁移
python manage.py migrate
九、性能优化技巧
1. 使用 select_related()
(用于 ForeignKey)
Post.objects.select_related('author').all()
2. 使用 prefetch_related()
(用于 ManyToManyField)
Post.objects.prefetch_related('tags').all()
3. 使用 only()
和 defer()
Post.objects.only('title', 'author') # 只加载部分字段
Post.objects.defer('content') # 排除某些字段
4. 使用 exists()
判断是否存在
Post.objects.filter(title='Django').exists()
十、总结
Django ORM 是一个强大而灵活的数据库抽象层,它让开发者可以用 Python 代码操作数据库,极大提升了开发效率和代码可维护性。
本文我们讲解了:
- ORM 的基本概念和优势
- 如何定义模型、字段和关系
- 查询操作(filter、exclude、order_by 等)
- 聚合与统计
- Meta 元类配置
- 模型方法
- 迁移命令
- 性能优化技巧
掌握 Django ORM 是使用 Django 构建 Web 应用的关键技能。接下来你可以深入学习:
- 自定义查询(Raw SQL、extra)
- 数据库函数(如 Concat、Substr)
- 使用事务(transaction)
- 使用数据库索引优化查询性能
十一、参考资料
Models | Django documentation | Django