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默认
icontainsILIKE %value%大小写不敏感包含
inIN (list)
gte/lte>= / <=
rangeBETWEEN a AND b
isnullIS NULL