Django ORM
Django ORM(对象关系映射)是 Django 框架中操作数据库的核心工具,它允许开发者通过 Python 代码(而非 SQL)实现对数据库的增删改查。
示例模型:
# models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100) # 字符串类型
age = models.IntegerField() # 整数类型
email = models.EmailField(null=True, blank=True) # 允许为空
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
publish_date = models.DateField()
price = models.DecimalField(max_digits=10, decimal_places=2)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="books") # 一对多关联(外键)
class Meta:
ordering = ["-publish_date"] # 默认按发布日期倒序排序
db_table = "my_books" # 自定义表名(默认是app名_模型名)
def __str__(self):
return self.title

一、查询操作
1. 基础查询
all():获取所有数据(返回 QuerySet)
all_books = Book.objects.all() # 等价于 SELECT * FROM my_books;
get():获取单个数据(必须匹配 1 条,否则抛DoesNotExist或MultipleObjectsReturned异常)
book = Book.objects.get(id=1) # 等价于 SELECT * FROM my_books WHERE id=1;
filter():过滤数据(返回满足条件的 QuerySet)
# 查询价格大于50的书
expensive_books = Book.objects.filter(price__gt=50)
exclude():排除满足条件的数据(与filter相反)
# 查询价格不大于50的书
cheap_books = Book.objects.exclude(price__gt=50)
2. 字段查询(双下划线__语法)
通过字段名__条件实现复杂过滤,常见条件:
__exact:精确匹配(默认,可省略)
Book.objects.filter(title__exact="Django入门") # 等价于 title = "Django入门"
__contains:包含指定字符串(模糊查询)
Book.objects.filter(title__contains="Django") # 标题包含"Django"
__gt/__lt/__gte/__lte:大于 / 小于 / 大于等于 / 小于等于
Book.objects.filter(price__gte=30, price__lte=100) # 价格30-100之间
__in:在指定列表中
Book.objects.filter(author__id__in=[1, 3, 5]) # 作者id为1、3、5的书
__isnull:是否为 NULL
Author.objects.filter(email__isnull=True) # 未填写邮箱的作者
- 日期相关:
__year/__month/__day
Book.objects.filter(publish_date__year=2023) # 2023年出版的书
3. 排序
order_by():指定排序字段(默认升序,加-表示降序)
# 按价格升序(从低到高)
books_by_price = Book.objects.order_by("price")
# 按发布日期降序(最新的在前)
books_by_date = Book.objects.order_by("-publish_date")
4. 切片与分页
- 切片:类似列表切片(仅支持正索引,且不支持负步长)
first_3_books = Book.objects.all()[:3] # 获取前3条数据
- 分页(用
Paginator):
from django.core.paginator import Paginator
all_books = Book.objects.all()
paginator = Paginator(all_books, 10) # 每页10条
page1 = paginator.page(1) # 第1页数据
page1.object_list # 第1页的具体数据
5. 聚合与注解
aggregate():对查询集进行聚合计算(返回字典)
from django.db.models import Avg, Sum, Count
# 计算所有书的平均价格
avg_price = Book.objects.aggregate(avg=Avg("price")) # {'avg': 65.5}
# 计算总共有多少本书
total_books = Book.objects.aggregate(count=Count("id")) # {'count': 20}
annotate():为每个对象添加 “注解”(额外字段)
# 给每个作者添加“书籍数量”注解
authors_with_book_count = Author.objects.annotate(book_count=Count("books"))
# 访问:author.book_count 即可获取该作者的书籍数量
三、新增数据
1. 单个新增
- 方式 1:实例化模型 +
save()
author = Author(name="张三", age=30)
author.save() # 保存到数据库(执行INSERT)
- 方式 2:
create()(直接创建并保存,更简洁)
book = Book.objects.create(
title="Python高级编程",
publish_date="2023-01-15",
price=89.00,
author=author # 关联已有的Author对象
)
2. 批量新增
bulk_create,效率更高
books = [
Book(title="book1", publish_date="2023-01-01", price=50, author=author),
Book(title="book2", publish_date="2023-01-02", price=60, author=author),
]
Book.objects.bulk_create(books) # 批量插入(仅1条SQL)
四、更新数据
1. 单个更新
book = Book.objects.get(id=1)
book.price = 99.00 # 修改属性
book.save() # 保存(执行UPDATE)
2. 批量更新
update(),直接执行 SQL,不加载对象到内存
# 将所有2020年前出版的书价格提高10元
Book.objects.filter(publish_date__year__lt=2020).update(price=F("price") + 10)
五、删除数据
1. 单个删除
book = Book.objects.get(id=1)
book.delete() # 执行DELETE
2. 批量删除
# 删除价格低于20的书
Book.objects.filter(price__lt=20).delete()
注意:外键关联中,
on_delete=models.CASCADE会触发级联删除(如删除作者时,其关联的书籍也会被删除)。
六、关联查询(外键 / 多对多)
1. 一对多
如Author→Book,外键在Book中
- 从 “一” 查 “多”:通过
related_name(模型中定义的related_name="books")
author = Author.objects.get(id=1)
author.books.all() # 获取该作者的所有书籍(等价于 Book.objects.filter(author=author))
- 从 “多” 查 “一”:直接访问外键字段
book = Book.objects.get(id=1)
book.author # 获取这本书的作者(返回Author对象)
2. 多对多
如Tag与Book,假设Book有tags = models.ManyToManyField(Tag)
- 添加关联:
add()
tag1 = Tag.objects.get(id=1)
tag2 = Tag.objects.get(id=2)
book.tags.add(tag1, tag2) # 给书籍添加标签
- 移除关联:
remove()
book.tags.remove(tag1) # 移除标签
- 清空关联:
clear()
book.tags.clear() # 清空所有标签
七、高级查询(F/Q 表达式)
1. F()
引用字段值(用于字段间比较或更新)
from django.db.models import F
# 查询“销量”大于“库存”的商品(假设有sales和stock字段)
Product.objects.filter(sales__gt=F("stock"))
# 给所有书的销量+10
Book.objects.update(sales=F("sales") + 10)
2. Q()
组合复杂条件(支持|(或)、&(且)、~(非))
from django.db.models import Q
# 查询“价格>100 或 2023年出版”的书
Book.objects.filter(Q(price__gt=100) | Q(publish_date__year=2023))
# 查询“不是张三写的 且 价格<50”的书
Book.objects.filter(~Q(author__name="张三") & Q(price__lt=50))
八、其他常用方法
count():获取查询集数量
Book.objects.filter(author__name="张三").count() # 张三的书籍数量
exists():判断查询集是否有数据(比count()>0高效)
if Book.objects.filter(title="Django").exists():
print("存在该书籍")
values()/values_list():只获取指定字段(返回字典 / 元组列表,减少内存占用)
# values():返回字典列表({字段:值})
Book.objects.values("title", "price") # [{'title': 'xxx', 'price': 89}, ...]
# values_list():返回元组列表((值1, 值2)),flat=True可转为单值列表
Book.objects.values_list("title", flat=True) # ['xxx', 'yyy', ...]
发表评论