Django ORM 核心操作详解
基础查询方法
掌握以下核心查询方法是使用 Django ORM 的基础:
<1> all(): 获取全部记录
<2> filter(**kwargs): 筛选符合条件的对象集合
<3> get(**kwargs): 获取唯一匹配对象,多重或无匹配会报错
<4> exclude(**kwargs): 排除符合条件的对象
<5> values(*field): 返回字典形式的查询结果
<6> values_list(*field): 返回元组形式的查询结果
<7> order_by(*field): 按指定字段排序结果
<8> reverse(): 反转查询结果顺序
<9> distinct(): 去除重复记录
<10> count(): 统计匹配对象数量
<11> first(): 获取首条记录
<12> last(): 获取末条记录
<13> exists(): 判断是否存在匹配记录
返回 QuerySet 的方法
- all()
- filter()
- exclude()
- order_by()
- reverse()
- distinct()
特殊 QuerySet 类型
- values() - 返回字典序列
- values_list() - 返回元组序列
返回具体对象的方法
- get()
- first()
- last()
返回布尔值的方法
- exists()
返回数值的方法
- count()
双下划线查询技巧
models.Product.objects.filter(id__lt=10, id__gt=1) # id 在 1-10 之间
models.Product.objects.filter(id__in=[11, 22, 33]) # id 匹配列表值
models.Product.objects.exclude(id__in=[11, 22, 33]) # id 不在列表中
models.Product.objects.filter(name__contains="tech") # 名称包含特定字符
models.Product.objects.filter(name__icontains="tech") # 忽略大小写包含
models.Product.objects.filter(id__range=[1, 3]) # 范围查询
models.Product.objects.filter(create_time__year=2023) # 按年份筛选日期
外键关系操作
正向查询
对象方式:
product_obj = models.Product.objects.first()
print(product_obj.category) # 关联分类对象
print(product_obj.category.name) # 分类名称
字段方式:
models.Product.objects.values_list("category__name")
反向查询
对象方式:
category_obj = models.Category.objects.first()
products = category_obj.product_set.all() # 该分类下的所有产品
titles = products.values_list("title") # 产品标题列表
字段方式:
models.Category.objects.values_list("product__title")
多对多关系管理
RelatedManager 方法
create() - 创建并关联新对象
models.Author.objects.first().book_set.create(
title="Python进阶",
publish_date=datetime.date.today()
)
add() - 添加现有对象到关联集合
author_list = models.Author.objects.filter(id__lt=3)
models.Book.objects.first().authors.add(*author_list)
# 或使用 ID
models.Book.objects.first().authors.add(*[1, 2])
set() - 更新整个关联集合
book_obj = models.Book.objects.first()
book_obj.authors.set([2, 3])
remove() - 移除指定关联对象
book_obj = models.Book.objects.first()
book_obj.authors.remove(3)
clear() - 清空所有关联
book_obj = models.Book.objects.first()
book_obj.authors.clear()
聚合与分组查询
聚合查询
from django.db.models import Avg, Sum, Max, Min, Count
# 基础聚合
models.Book.objects.all().aggregate(Avg("price"))
# {'price__avg': 13.233333}
# 自定义聚合名
models.Book.objects.aggregate(avg_price=Avg('price'))
# {'avg_price': 13.233333}
# 多重聚合
models.Book.objects.all().aggregate(
Avg("price"),
Max("price"),
Min("price")
)
分组查询
# 按出版社分组统计最低价格
models.Publisher.objects.annotate(
min_price=Min("book__price")
).values("name", "min_price")
# 统计每本书作者数量
models.Book.objects.all().annotate(
author_count=Count("author")
)
# 查询多作者书籍
models.Book.objects.annotate(
author_count=Count("author")
).filter(author_count__gt=1)
F 表达式与 Q 对象
F 表达式
用于字段间比较和更新:
from django.db.models import F
# 查询评论数大于收藏数的书籍
models.Book.objects.filter(comment_num__gt=F('favorite_num'))
# 数值运算
models.Book.objects.filter(comment_num__lt=F('favorite_num')*2)
# 字段更新
models.Book.objects.all().update(price=F("price")+30)
# 字符串字段更新
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.all().update(
title=Concat(F("title"), Value("(第2版)"))
)
Q 对象
实现复杂逻辑查询:
# OR 查询
models.Book.objects.filter(
Q(authors__name="张三") | Q(authors__name="李四")
)
# AND + NOT 组合
models.Book.objects.filter(
Q(author__name="王五") & ~Q(publish_date__year=2023)
)
# 参数混合使用(Q对象需在前)
models.Book.objects.filter(
Q(publish_date__year=2023) | Q(publish_date__year=2022),
title__icontains="教程"
)
并发控制与事务
行级锁
# SELECT ... FOR UPDATE
entries = Entry.objects.select_for_update().filter(
author=request.user
)
# 非阻塞锁
Entry.objects.select_for_update(nowait=True)
# 跳过已锁定行
Entry.objects.select_for_update(skip_locked=True)
事务处理
try:
from django.db import transaction
with transaction.atomic():
publisher = models.Publisher.objects.create(
name="新星出版社"
)
models.Book.objects.create(
title="Django实战",
publisher=publisher
)
except Exception as e:
print(f"事务失败: {e}")
原生 SQL 执行
使用 raw() 方法
# 基础原生查询
for person in Person.objects.raw('SELECT * FROM myapp_person'):
print(person)
# 字段映射
Person.objects.raw(
'SELECT id, first_name as fname FROM myapp_person',
translations={'first_name': 'fname'}
)
# 带参数查询
Person.objects.raw(
'SELECT * FROM myapp_person WHERE id > %s',
params=[1]
)
直接执行 SQL
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT * FROM auth_user WHERE id = %s", [1])
result = cursor.fetchone()
调试工具
在 settings.py 中启用 SQL 日志:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
}
}
独立脚本中使用 Django ORM
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
import django
django.setup()
from app.models import Book
books = Book.objects.all()
print(books)