给定以下模型:
User
--------
Thread
--------
Post
--------
thread: ForeignKey(Thread)
read_by: ManyToManyField(User)
现在,我想检索当前登录用户阅读的特定线程的所有帖子。
因此,我从获取帖子开始:
Post.objects.filter(thread=self.thread)
现在,我不确定如何在将已读/未读标志设置为真/假的情况下进行注释。当前登录的用户可以使用变量self.request.user
。
我们可以在这里做一个EXISTS
子查询,通过查询隐式构造的 Django 的 "through" 模型:
from django.db.models import Exists, OuterRef
post_read_query = Post.ready_by.through.objects.filter(
user_id=self.request.user.pk,
post_id=OuterRef('pk')
)
然后,我们在Exists
子查询 [Django-doc] 中使用此post_read_query
:
Post.objects.filter(thread=self.thread).annotate(
is_read=Exists(post_read_query)
)
由此产生的Post
对象将具有一个额外的属性.is_read
,该属性True
给定用户已读取Post
(self.request.user
)。
这将生成如下所示的查询:
SELECT post.*,
EXISTS(
SELECT U0.id, U0.user_id, U0.post_id
FROM post_read_by U0
WHERE U0.post_id = post.id AND U0.user_id =user_id
) AS is_read
FROM post
WHERE post.thread_id =thread_id