Django ORM 参考
Django ORM 全面指南:QuerySet 操作、过滤、聚合、关联和性能优化。
1. QuerySet 基础
from myapp.models import Article, Author
# 获取全部
articles = Article.objects.all()
# filter 与 exclude
active = Article.objects.filter(is_published=True)
not_draft = Article.objects.exclude(status="draft")
# 链式调用(惰性,只在求值时执行 SQL)
recent = (Article.objects
.filter(is_published=True)
.order_by("-created_at")[:10])
# 获取或创建
obj, created = Article.objects.get_or_create(
slug="hello-world",
defaults={"title": "Hello World"},
)
# 批量操作
Article.objects.bulk_create([Article(title=t) for t in titles])
Article.objects.filter(status="draft").update(status="published")
2. 字段查找
# 字符串查找
Article.objects.filter(title__icontains="python")
Article.objects.filter(slug__startswith="how")
# 数值/日期比较
Article.objects.filter(view_count__gte=1000)
Article.objects.filter(created_at__year=2024)
Article.objects.filter(published_at__range=("2024-01-01", "2024-12-31"))
# 关系跨越(双下划线)
Article.objects.filter(author__name="Alice")
Article.objects.filter(tags__name__in=["python", "django"])
# 空值检查
Article.objects.filter(published_at__isnull=True)
3. Q 对象与 F 表达式
from django.db.models import Q, F
# Q 对象 — 复杂布尔逻辑
Article.objects.filter(Q(status="published") | Q(featured=True))
Article.objects.filter(Q(author__name="Alice") & ~Q(category="spam"))
# F 表达式 — 引用字段值
# 无需 Python 往返即可递增浏览量
Article.objects.filter(pk=1).update(view_count=F("view_count") + 1)
# 比较两个字段
Article.objects.filter(updated_at__gt=F("created_at"))
4. 聚合与注解
from django.db.models import Count, Sum, Avg
# 聚合整个 QuerySet
stats = Article.objects.aggregate(
total=Count("id"),
avg_views=Avg("view_count"),
)
# 注解每一行
authors = Author.objects.annotate(
article_count=Count("articles"),
total_views=Sum("articles__view_count"),
).order_by("-article_count")
# values() + annotate = GROUP BY
Article.objects.values("category").annotate(
count=Count("id"),
).order_by("-count")
5. select_related 与 prefetch_related
from django.db.models import Prefetch
# select_related — JOIN(适用于外键/一对一,单条查询)
articles = Article.objects.select_related("author", "category").all()
# prefetch_related — 单独查询(适用于多对多/反向外键)
articles = Article.objects.prefetch_related("tags", "comments").all()
# 自定义预取
articles = Article.objects.prefetch_related(
Prefetch("comments",
queryset=Comment.objects.filter(is_approved=True),
to_attr="approved_comments")
)
# 仅选择特定列
Article.objects.only("id", "title", "slug")
Article.objects.defer("content", "metadata")
6. 常用查找后缀
| 查找 | SQL 等价 | 说明 |
|---|---|---|
| exact | = value | 默认 |
| icontains | ILIKE %value% | 大小写不敏感包含 |
| in | IN (list) | — |
| gte/lte | >= / <= | — |
| range | BETWEEN a AND b | — |
| isnull | IS NULL | — |