R / Richie全部文章 ↑

Python · 2 分钟阅读

Model 查询 API

Manager 是入口,QuerySet 是结果,惰性求值是关键。

创建实例

# save
book = Book(title="新书", author="小明")
book.save()

# create(一步完成)
Book.objects.create(title="新书", author="小明")

# get_or_create(不存在则创建)
obj, created = Book.objects.get_or_create(
    title="新书", defaults={"author": "小明"}
)

返回单实例

Book.objects.get(pk=1)        # 不存在抛 DoesNotExist
Book.objects.first()
Book.objects.last()
Book.objects.earliest("pub_date")
Book.objects.latest("pub_date")

返回 QuerySet

Book.objects.all()                                 # 全部
Book.objects.filter(title__contains="Django")      # 过滤
Book.objects.exclude(is_active=False)              # 反过滤
Book.objects.order_by("-created_time")             # 排序
Book.objects.reverse()                             # 反转
Book.objects.distinct()                            # 去重
Book.objects.values("id", "title")                 # 字典
Book.objects.values_list("id", flat=True)          # 元组/标量
Book.objects.only("title")                         # 仅取 title
Book.objects.defer("content")                      # 排除 content

切片

Book.objects.all()[:10]            # 前 10 条(推荐)
Book.objects.all()[10:20]          # LIMIT/OFFSET
Book.objects.all()[::2]            # step 模式(会立刻求值)

不支持负索引;切片结果是新的 QuerySet,可继续 .filter()。

链式查询

Book.objects.filter(
    title__icontains="django",
    pub_date__year=2025,
).order_by("-pub_date")[:20]

字段查找

关键字 SQL 等价
exact / iexact = / LIKE(大小写不敏感)
contains / icontains LIKE %x%
startswith / endswith LIKE x% / LIKE %x
gt / gte / lt / lte > / >= / < / <=
in IN (...)
range BETWEEN
isnull IS NULL
year / month / day 提取日期部分

关联查询

# 跨表正向:双下划线
Comment.objects.filter(topic__title__contains="Django")
Comment.objects.filter(topic__user__username="admin")

# 反向:小写模型名
Topic.objects.filter(comment__up__gte=10)

反向管理器默认名 <model>_set,可通过 related_name 覆盖。

更新与删除

# save:逐字段
book = Book.objects.get(pk=1)
book.title = "新标题"
book.save()

# update:SQL UPDATE,更高效
Book.objects.filter(pk=1).update(title="新标题")

# delete
book.delete()
Book.objects.filter(is_active=False).delete()

update / delete 返回受影响行数。

聚合与分组

from django.db.models import Avg, Count, Max, Min, Sum

Book.objects.aggregate(avg_price=Avg("price"))
# {"avg_price": 59.0}

# 分组:每个作者的图书数
Book.objects.values("author").annotate(n=Count("id"))

F 对象 & Q 对象

from django.db.models import F, Q

# F:字段间比较
Book.objects.filter(views__gt=F("likes") * 2)

# Q:复杂条件组合
Book.objects.filter(
    Q(price__lt=50) | Q(is_hot=True),
    Q(is_active=True),
)

性能小贴士

  • count() 比 len(qs) 高效(前者 SQL COUNT(*))
  • exists() 比 count() > 0 高效(SQL LIMIT 1)
  • 用 select_related / prefetch_related 减少 N+1
  • 用 iterator() 流式处理大数据集
  • 打印 .query 查看生成的 SQL:print(qs.query)