导读:本期聚焦于小伙伴创作的《Django项目怎么进行模型字段优化?Python使用defer与only减少查询开销》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Django项目怎么进行模型字段优化?Python使用defer与only减少查询开销》有用,将其分享出去将是对创作者最好的鼓励。

在Django项目开发过程中,数据库查询的性能优化是绕不开的话题,很多时候我们编写查询逻辑时,默认会获取模型的所有字段,但实际上部分场景下只需要用到其中几个字段,全字段查询会额外消耗数据库IO和内存资源。Django ORM提供的defer和only方法,就是专门用来优化这类场景的,能够让我们按需指定需要查询或者延迟查询的字段,从而降低查询开销。

Django项目怎么进行模型字段优化?Python使用defer与only减少查询开销

defer方法的使用

defer方法的作用是延迟加载指定的字段,也就是说,当我们使用defer指定某些字段后,这些字段不会在首次查询时从数据库中获取,只有当后续实际访问这些字段的时候,才会单独发起查询获取对应的值。

假设我们有一个用户模型UserProfile,包含id、username、email、avatar、bio等多个字段,很多时候我们只需要展示用户名,不需要获取头像和个人简介这些大字段,就可以用defer延迟这两个字段的查询。

# 定义用户模型
from django.db import models

class UserProfile(models.Model):
    username = models.CharField(max_length=50)
    email = models.EmailField()
    avatar = models.ImageField(upload_to='avatar/')
    bio = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

# 延迟查询avatar和bio字段
users = UserProfile.objects.defer('avatar', 'bio')
for user in users:
    # 此时访问username和email不会触发额外查询
    print(user.username, user.email)
    # 访问avatar时会触发额外的数据库查询获取该字段的值
    # print(user.avatar)

defer方法的注意事项

  • defer可以接收多个字段名作为参数,同时延迟多个字段的加载。
  • 如果后续访问了被延迟的字段,Django会单独发起一次查询获取该字段,所以如果确定后续不会用到这些字段,用defer才有优化效果。
  • 不能延迟主键字段,因为Django ORM需要通过主键来标识模型实例,延迟主键会导致查询异常。

only方法的使用

only方法和defer的作用相反,它是指定只查询哪些字段,没有在only参数中指定的字段都会被延迟加载,只有后续访问的时候才会单独查询。

还是以上面的UserProfile模型为例,如果我们只需要用户名和邮箱两个字段,就可以用only指定这两个字段,其他字段都会被延迟。

# 只查询username和email字段,其他字段延迟加载
users = UserProfile.objects.only('username', 'email')
for user in users:
    # 访问指定字段不会触发额外查询
    print(user.username, user.email)
    # 访问未指定的字段会触发额外查询
    # print(user.bio)

only方法的注意事项

  • only中指定的字段会立即查询,其他字段默认延迟,和defer的逻辑是互补的。
  • 如果同时使用了only和defer,defer指定的字段会覆盖only中的对应字段,也就是defer指定的字段即使被only包含,也会被延迟。
  • 同样不能指定主键字段,主键默认会被查询,不需要额外加到only参数中。

defer和only的区别与选择

两者的核心区别在于指定字段的逻辑不同:defer是指定哪些字段不查,only是指定哪些字段要查,其他字段都不查。在实际开发中可以根据场景选择:

  • 如果大部分字段都需要用到,只有少数几个字段不需要,优先用defer,比如模型有很多字段,只需要排除两三个大字段,用defer更方便。
  • 如果只需要用到少数几个字段,大部分字段都不需要,优先用only,比如只需要展示两个字段,用only更直观。

我们可以通过打印查询的SQL语句来验证两者的效果,Django可以通过queryset.query查看生成的SQL:

# 查看defer生成的SQL
defer_qs = UserProfile.objects.defer('avatar', 'bio')
print(defer_qs.query)
# 输出的SQL会包含除了avatar和bio之外的所有字段

# 查看only生成的SQL
only_qs = UserProfile.objects.only('username', 'email')
print(only_qs.query)
# 输出的SQL只会查询id、username、email三个字段,id是主键默认包含

使用场景总结

defer和only适合用在以下场景:

  • 模型字段较多,且部分字段是大字段(比如长文本、图片字段),查询时不需要用到这些大字段,用defer排除。
  • 列表页展示只需要少量字段,比如用户列表只需要用户名和注册时间,用only指定这两个字段即可。
  • 避免N+1查询的辅助优化,比如关联查询时,主表只需要少量字段,可以配合only减少查询的字段数量。

需要注意的是,这两个方法只是减少单次查询的字段数量,不会减少查询的次数,如果后续频繁访问被延迟的字段,反而会增加查询次数,所以一定要根据实际业务场景判断是否真的不会用到被延迟的字段,再决定是否使用这两个优化方法。

Djangodeferonly模型字段优化查询开销修改时间:2026-07-21 09:27:25

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。