select_related()
返回一个带有外键关系的QuerySet,在执行查询时可以选择其他关联对象的数据,这是一个性能增强,这样可以做更复杂的查询,而且意味着以后使用外键关系不需要再次做数据库查询。
下面的例子解释了普通查询和select_related()查询的区别, 下面是一个标准查询:
# 访问数据库
e = Entry.objects.get(id=1)
# 在此访问数据库以得到关联的Blog对象(外键)
b = e.blog
select_related()查询:
# 访问数据库
e = Entry.objects.select_related('blog').get(id=1)
# 不会访问数据库,因为e.blog已经在前面的查询中预先填充
b = e.blog
select_related()可以用于objects的所有查询集:
from django.uils import timezone
# 查询所有计划在未来发布的博客
blogs = set()
for e in Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog'):
# 如果没有select_related(),每一次循环都会查询一次数据库去取每一个entry关联的blog
blogs.add(e.blog)
filter()和select_related()的顺序无所谓,下面两条查询是一样的:
Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())
可以用类似的方式查询外键,例如下面的models:
from django.db import models
class City(models.Model):
# ...
pass
class Person(models.Model):
# ...
hometown = models.ForeignKey(
City,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
class Book(models.Model):
# ...
author = models.ForeignKey(Person, on_delete=models.CASCADE)
然后这条查询Book.objects.select_related('author__hometown').get(id=4)会缓存关联的Person和与Person关联的City。
# 通过与author和hometown表的连接访问数据库,缓存好author和hometown
b = Book.objects.select_related('author__hometown').get(id=4)
p = b.author # 不会访问数据库
c = p.hometown # 不会访问数据库
# Without select_related()...
b = Book.objects.get(id=4) # Hits the database.
p = b.author # 访问数据库
c = p.hometown # 访问数据库
你可以在传递给select_related()的字段列表中引用任何ForeignKey或OneToOneField关系。
如果需要清除QuerySet上以前的select_related调用添加的关联字段,可以传递一个None作为参数:
without_relations = queryset.select_related(None)
select_related可以链式调用,也就是说,select_related('foo', 'bar')等同于select_related('foo').select_related('bar')