Django中get()与filter()对比

在 Django 中,get()filter() 是 QuerySet API 中用于检索数据的两个核心方法,它们的功能和使用场景有明显区别。以下是详细对比:

1. 核心区别

特性 get() filter()
返回值 单个对象(模型实例) 查询集(QuerySet,可迭代)
数量限制 必须精确匹配1个对象 可以匹配0个、1个或多个对象
对象不存在时 抛出 DoesNotExist 异常 返回空查询集(不报错)
多对象匹配时 抛出 MultipleObjectsReturned 异常 返回包含多个对象的查询集
链式调用 不支持(返回的是模型实例) 支持(可继续添加过滤条件)

2. 语法与示例

get() 的用法
python 复制代码
# 获取 ID 为 1 的书(必须存在且唯一)
book = Book.objects.get(id=1)

# 等价的手动异常处理
try:
    book = Book.objects.get(id=1)
except Book.DoesNotExist:
    # 处理不存在的情况
    pass
except Book.MultipleObjectsReturned:
    # 处理多对象匹配的情况
    pass
filter() 的用法
python 复制代码
# 获取所有已发布的书(可能有0本或多本)
books = Book.objects.filter(status='published')

# 链式过滤:获取已发布且价格大于 50 的书
books = Book.objects.filter(status='published').filter(price__gt=50)

# 等价的单语句写法
books = Book.objects.filter(status='published', price__gt=50)

# 获取第一本书或 None(推荐替代 get() 的安全写法)
first_book = books.first()  # 等价于 books[0] if books else None

3. 性能对比

  • get() :直接查询单条记录,生成的 SQL 类似 SELECT ... WHERE ... LIMIT 1,理论上更高效。
  • filter().first() :生成的 SQL 是 SELECT ... WHERE ... LIMIT 1,与 get() 几乎相同,但多了一步 Python 对象转换,性能损耗可忽略不计。

注意 :在查询条件唯一(如主键查询)时,两者性能接近;但 filter().first() 更安全。

4. 适用场景

推荐使用 get() 的场景
  • 查询条件唯一(如通过主键或唯一键查询)。

  • 对象必须存在,否则视为程序错误(如配置项、固定ID的系统数据)。

  • 示例

    python 复制代码
    user = User.objects.get(username='admin')  # 管理员用户必须存在
推荐使用 filter() 的场景
  • 查询条件不唯一(如按类别筛选商品)。

  • 结果可能为空(如搜索功能)。

  • 需要链式查询(如分页、排序、多条件组合)。

  • 示例

    python 复制代码
    # 搜索功能(结果可能为空)
    books = Book.objects.filter(title__icontains='python')
    
    # 分页查询
    books = Book.objects.filter(category='tech').order_by('-pub_date')[:10]

5. 常见错误案例

错误使用 get() 的场景
python 复制代码
# 错误:title 可能不唯一,导致 MultipleObjectsReturned
book = Book.objects.get(title="Python")

# 正确:使用 filter().first()
book = Book.objects.filter(title="Python").first()
低效的 filter() 使用
python 复制代码
# 低效:两次数据库查询
if Book.objects.filter(id=1).exists():
    book = Book.objects.get(id=1)  # 重复查询

# 高效:单次查询
book = Book.objects.filter(id=1).first()

6. 总结

场景 方法
通过主键/唯一键获取单个对象 get()(需确保存在)
安全获取单个对象(不存在时返回 None) filter().first()
查询可能存在多个结果或空结果 filter()
需要链式查询(如分页、排序) filter()

建议 :优先使用 filter().first() 替代 get(),除非你能绝对保证查询条件的唯一性和存在性。

相关推荐
千里码aicood44 分钟前
springboot+vue心理健康服务小程序(源码+文档+调试+基础修改+答疑)
数据库·vue.js·spring boot
麦兜*1 小时前
Redis高可用架构设计:主从复制、哨兵、Cluster集群模式深度对比
java·数据库·spring boot·redis·spring·spring cloud·缓存
王嘉俊9251 小时前
Redis 入门:高效缓存与数据存储的利器
java·数据库·redis·后端·spring·缓存·springboot
王维1 小时前
【shardingsphere-jdbc】分表实践
java·数据库
xxy.c1 小时前
基于IMX6ULL芯片--I2C总线简单应用
数据库·mongodb
cookqq1 小时前
MongoDB源码分析慢日志:从配置到实现的完整解析
数据库·mongodb·nosql·慢日志
8K超高清1 小时前
汇世界迎全运 广州国际社区运动嘉年华举行,BOSMA博冠现场展示并分享与科技全运的故事
运维·服务器·网络·数据库·人工智能·科技
come112342 小时前
深入Spring Boot生态中最核心部分 数据库交互spring-boot-starter-data-jpa和Hibernate (指南五)
数据库·spring boot·hibernate
不剪发的Tony老师2 小时前
dbswitch:一款免费开源、功能强大的异构数据库迁移同步工具
数据库·etl·dbswitch
Crazy________3 小时前
13MySQL主从复制原理与搭建指南
数据库·mysql