Django的prefetch_related()函数是用于优化ORM数据库查询的函数,用于在获取QuerySet集合时通过一部查询获取一些相关联的数据。
该函数使用场景为在一对多或者多对多的场景下,查询主表数据时,预先自动查询对应的外键关联表数据,并将查询结果一起返回,可以的提高数据检索的效率,减少查询数据库的次数。
prefetch_related()函数的使用方法如下:
从单个关联属性开始,该属性会在后续查询中被提前预存。
Model.objects.prefetch_related('related_attr').get(pk=1)
# 查询所有实例时预存,这样将能够减少一次查询
qs = Model.objects.prefetch_related('related_attr')
# 在'prefetch_related'调用链上添加额外的关系
qs = qs.prefetch_related('other_attr')
# 在与其他时间消耗较长的查询连通中使用
Model.objects.prefetch_related(Prefetch('categories', queryset=Categories.objects.filter(is_published=True)))
其中,’related_attr’是与Model模型相关联的外键属性、正向多对多属性或反向多对多属性。’other_attr’是与’prefetch_related’方法调用已有关联的实例中某个属性相关联的外键属性、正向多对多属性或反向多对多属性。
下面给出两个具体实例,以说明prefetch_related()函数的作用。
1、查询文章列表时,预处理并提取出文章的标签信息
# models.py
class Article(models.Model):
title = models.CharField(max_length=50)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
class Tag(models.Model):
name = models.CharField(max_length=20)
articles = models.ManyToManyField(Article)
# views.py
def article(request):
articles = Article.objects.prefetch_related('tag_set').order_by('-pub_date')
return render(request, 'article_list.html', {'articles': articles})
# article_list.html
{% for article in articles %}
<h2>{{ article.title }}</h2>
<p>{{ article.content }}</p>
<ul>
{% for tag in article.tag_set.all %}
<li>{{ tag.name }}</li>
{% endfor %}
</ul>
{% endfor %}
可以看到,在视图函数中,我们使用 prefetch_related() 函数预先提前查询与文章相关联的标签信息,然后在模板文件中使用 article.tag_set.all 获取文章的标签信息,避免了代码中多次查询数据库信息的问题,提高了查询效率。
2、查询城市列表时,预处理并提取出城市所在的省份信息
# models.py
class Province(models.Model):
name = models.CharField(max_length=20)
class City(models.Model):
name = models.CharField(max_length=20)
province = models.ForeignKey(Province, on_delete=models.CASCADE)
# views.py
def city(request):
provinces = Province.objects.prefetch_related('city_set').order_by('id')
return render(request, 'city_list.html', {'provinces': provinces})
# city_list.html
{% for province in provinces %}
<h2>{{ province.name }}</h2>
<ul>
{% for city in province.city_set.all %}
<li>{{ city.name }}</li>
{% endfor %}
</ul>
{% endfor %}
在视图函数中,我们使用 prefetch_related() 函数预先查询与省份相关联的城市信息,然后在模板中使用province.city_set.all获取与该省份相关联的所有城市信息,避免了多次查询数据库的问题,提高了查询效率。
综上,prefetch_related()函数提供了ORM数据检索的整洁调用方式,能够减少代码中的嵌套查询和提高数据访问效率。