说我有两个这样的模型:
from django.contrib.auth import User
class Post(models.Model):
text = models.TextField()
class Like(models.Model):
post = models.ForeignKey(Post)
user = models.ForeignKey(User)
我觉得很标准。用户可以喜欢的帖子表。
我想获取所有Post对象的查询集,如果当前用户(想象request.user
)喜欢它们,则使用该信息进行注释。
这样的事情(这当然是不正确的)
qs = Post.objects.all().annotate(like__user=request.user)
我想迭代qs并有一个属性说明当前用户是否喜欢这个帖子,如下所示:
for post in qs:
if post.current_user_liked:
# do something
我想使用注释的原因当然是性能,我想避免对每个帖子进行查询以检查是否存在Like with user = request.user。
答案 0 :(得分:4)
我认为您可以annotate()
与RawSQL
一起使用。
如果这不起作用,您可以将prefetch_related
与Prefetch
对象一起使用,以便Django通过一个额外查询加载所有相关的喜欢。
Post.objects.all().prefetch_related(
Prefetch('current_user_likes', queryset=Like.objects.filter(user=request.user))
)
然后当你遍历查询集时,你会这样做:
for post in qs:
if post.current_user_likes.all():
# do something
请注意,您在此处使用all()
,因为已经提取了结果。通常exists()
如果你不需要结果会更有效率,但在这里它会引起额外的查询。
答案 1 :(得分:1)
我最终采用了一种更简单的方法,因为我在视图中使用分页显示Post
个对象,因此Post
的{{1}}总是非常小。
另外,我显示由pk排序的queryset
个对象。
所以我的解决方案是构建Post
主要Post
主键的python列表,从我正在显示的帖子中选择(因此列表总是非常小):
request.user
然后在我的模板中,我只需检查每个pks = [ post.pk for post in queryset ]
first = pks[0]
last = pks[-1]
context['liked_posts'] = Like.objects.filter(user=request.user,
post_id__range=sorted([first, last])).values_list('post_id', flat=True)
pk是否在Post
列表中。
此方法仅需要对数据库进行额外查询。