【Django】什么时候使用select_related()或prefetch_related()
Django获取数据实体的时候,返回的对象一个实体或多个实体,也就是QuerySet,它是Django专有的东西,具体的理解,它是类似Python的字典的东西,但它并不实现字典的所有方法。今天讲解的是它其中的一个函数select_related()。
select_related()使用的场景,是获取实体的同时,能快速获取到它对应的外键关系实体。 如果获取实体时没有使用select_related(),要引用该实体的外键关系,那么就会重新连接数据库去获取对应实体了。比如 作者Author 博客Blog 两个表,他们的关系 是一个作者Author有多个博客blog,;当我们想获取到一个作者的同时 直接引用该作者的所有博客时,常规做法是会进行两次数据库连接的,但使用了select_related()后,情况就有所变化了,它第一次连接数据库获取该作者的时候,该作者的所有博客被获取到了。
比如:
author=Author.objects.select_related().get(pk=1) #获取id是1的作者; 获取该博客的同时已经获取到该作者的所有博客
blogs=author.blog #获取id是1作者的所有博客blogs ,这时并不需要连接数据库获取那些博客了。
不使用select_related()时:
author=Author.objects.get(pk=1) #获取id是1的作者;仅仅获取该作者的实体
blogs=author.blog #获取id是1作者的所有博客blogs ,但需要连接数据库获取该作者的那些博客。
select_related()提供了一个备选参数depth,执行获取对象关联实体的深度。如 select_related(depth=2),这时不仅仅获取到相关的博客,还能获取到博客的关联实体,比如博客的类别(另一个和blog表相对应的表)之类的。如果不指定depth,默认情况将会获取到该作者的所有关联对象的 包括关联对象的子关联对象。由此可以想象,使用它有利有弊,当自己需要对象相关关联对象的时候,可以使用它,只是这样第一次查询的时候,将进行不少表的操作(要看表关联复杂程度)。
所以当我们获取对象需要它相关联的对象时,就请用select_related()吧,如果该对象关联的表很多,请指定depth的值,避免资源的浪费;反之避免select_related()。
prefetch_related ()的使用:
表:
class City(models.Model):
name = models.CharField(max_length=5)
province = models.ForeignKey(Province)
def unicode(self):
return self.name
class Person(models.Model):
firstname = models.CharField(max_length=10)
lastname = models.CharField(max_length=10)
visitation = models.ManyToManyField(City, related_name = “visitor”)
hometown = models.ForeignKey(City, related_name = “birth”)
living = models.ForeignKey(City, related_name = “citizen”)
def unicode(self):
return self.firstname + self.lastname
要获得张三所有去过的城市。首先注意到Persion.visitation的类型是ManyToManyField,在数据库中,Person表有多个人,City表有多个城市。我们要在通过循环打印张三去过的这些城市前,通过张三的“id”限制将相关联的城市预取出来,存到内存中,而不是在打印这些城市的时候再去数据库查找(lazy loading),减少了数据库查询次数。
zhangs= Person.objects.prefetch_related(‘visitation’).get(firstname=u”张”,lastname=u”三”)
for city in zhangs.visitation.all() :
… print city
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY