我有一些帖子里面有树评论。评论也有喜欢的。我已经设法优化了SQL查询,与帖子本身相关的普通评论不会创建新的查询,但对其他评论的回答仍然会创建3-4个新的数据库请求。我能以某种方式减少查询的数量吗?我一直在使用prefetch_related来实现这个目的。
我的帖子模型:
class Post(models.Model):
author = models.ForeignKey(
User,
on_delete=models.CASCADE
)
title = models.CharField(
max_length=200,
null=True,
blank=True
)
header_image = models.ImageField(
null=True,
blank=True,
upload_to="posts/headers",
help_text='Post will start from this image'
)
body = CharField(
max_length=500
)
post_date = models.DateTimeField(
auto_now_add=True
)
likes = models.ManyToManyField(
User,
through='UserPostRel',
related_name='likes',
help_text='Likes connected to the post',
)
def total_likes(self):
return self.likes.count()
评论模型
class Comment(models.Model):
user = models.ForeignKey(User, related_name='comment_author', on_delete=models.CASCADE)
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
body = models.TextField(max_length=255)
comment_to_reply = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name='replies')
likes = models.ManyToManyField(User, through='CommentLikeRelation', related_name='comment_likes')
created_at = models.DateTimeField(auto_now_add=True)
def replies_count(self):
return self.replies.count()
def total_likes(self):
return self.likes.count()
def is_a_leaf(self):
return self.replies.exists()
def is_a_reply(self):
return self.comment_to_reply is not None
class CommentLikeRelation(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.ForeignKey(Comment, on_delete=models.CASCADE)
查看流程数据
def get(self, request, *args, **kwargs):
current_user = request.user
user_profile = User.objects.get(slug=kwargs.get('slug'))
is_author = True if current_user == user_profile else False
comment_form = CommentForm()
Posts = Post.objects.filter(author=user_profile.id)
.select_related('author')
.prefetch_related('likes')
.prefetch_related(
'comments',
'comments__user',
'comments__likes',
'comments__comment_to_reply',
'comments__replies',
'comments__replies__user',
'comments__replies__likes',
)
.order_by('-post_date')
)
return render(request, self.template_name,
context={
'is_author': is_author,
'current_user': current_user,
'profile': user_profile,
'form': comment_form,
'posts': posts,
})
1条答案
按热度按时间aiazj4mn1#
您可以使用
prefetch_related
方法在一个查询中预取相关的评论和回复,沿着它们的作者和喜欢的内容,这是减少查询次数的一种方法。Django的文档中解释了如何使用它,除此之外,这完全取决于你自己。例如,你可以修改
Comment
以包含一个related_name
用于回复(Django会为你处理),然后使用prefetch_related
进行相关的评论和回复,如下所示:这样,您可以在一个查询中获得所有相关的评论和回复,沿着它们的作者和喜欢的内容;Django将使用对象缓存来处理剩下的部分,只需要最少的额外查询。
或者,为了进一步优化,您可以使用
select_related
在单个查询中获取相关对象,而不是对每个对象进行附加查询;最后,将所需的金额注解为计算值: