首页 > 解决方案 > Django - prefetch_related 的使用

问题描述

无论我阅读了多少教程/文档,我仍然不太了解我应该如何使用 prefetch_related。

我的模型.py:

class ProfileComment(models.Model):
    author       = models.ForeignKey('Profile', on_delete=models.CASCADE, null=True)
    date_posted  = models.DateTimeField(default=timezone.now, editable=False)
    body         = models.CharField(max_length=180, blank=True)
    ...

class Profile(models.Model):
    user     = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    comments = models.ManyToManyField(ProfileComment, related_name='comments', blank=True)
    avatar   = models.FileField(upload_to=avatar_folder, default='user-avatar/default.png')
    ...

我的意见.py:

profile = Profile.objects.prefetch_related('comments').get(user=request.user)

在模板中:

{% for comment in profile.comments.all %}
<div>
  <p>Author: {{ comment.author.user }}</p><img src="{{ comment.author.avatar.url }}">
  <p>Message: {{ comment.body }}</p>
  <p>Date posted: {{ comment.date_posted }}</p>
</div>
{% endfor %}

但是,无论我在 prefetch_related 中输入什么,每条记录的查询量都会增加 5

标签: djangodjango-models

解决方案


.prefetch_related(…)[Django-doc]应该用于批量获取查询集的相关对象。既然你写:

.get(user=request.user)

但是它不会有任何区别,因为您只检索一个对象,因此它将在额外的查询中预取注释。

但是,您可以最小化的是源自comment.author.user. 这将使每个评论产生两个额外的查询,因为ForeignKeys 是延迟加载的。

因此,您的视图可能如下所示:

profile = Profile.objects.get(user=request.user)
comments = profile.comments.select_related('author', 'author__user')

您将profile和传递comments给模板,然后使用以下命令检索它:

{% for comment in comments %}
<div>
  <p>Author: {{ comment.author.user }}</p><img src="{{ comment.author.avatar.url }}">
  <p>Message: {{ comment.body }}</p>
  <p>Date posted: {{ comment.date_posted }}</p>
</div>
{% endfor %}

在这里,我们因此从查询集中读取评论,我们在同一查询中获取配置文件和该配置文件的用户。因此,我们将进行两个查询:一个查询,一个查询包括and在内的Profile所有Comments 。.author.author.user


推荐阅读