用多多关系中的布尔值注释查询集



假设我有一个Book模型:

class Book(models.Model)
title = models.Charfield(...)
likes = models.ManyToMany(User, related_name="books_liked")

我需要为当前登录的用户注释一个带有is_liked字段的查询集。

我有这个在视图中,但它不工作:

user = self.request.user
qs = Book.objects.all().annotate(is_liked=Exists(user.books_liked.all()))
return qs

所以我可以在模板中使用这样的内容

{% for book in books %}
{% if book.is_liked %}
...
{% endif %}
{% endfor %}

我正在检查这个文档部分,但我不太确定如何进行,或者如果是正确的方法。

https://docs.djangoproject.com/en/3.1/ref/models/expressions/exists-subqueries

我该怎么做?谢谢。

这有点晚了,但是。可以通过使用没有显式模型的SQL逻辑来解决这个问题。

from django.db.models import Case, When, Value
user_id = self.request.user.id
qs = Book.objects.annotate(is_liked=Case(
When(likes__id=user_id, then=Value(True)),
default=False
)        

其余的工作正常。

文档:案例

当超过1个用户喜欢同一本书时,这会导致一些奇怪的行为。因此,使用Q被证明是更有用的。但是,如果用户没有登录,则会抛出错误。所以用一个尝试,除了块它工作。修复方法如下:

from django.db.models import Q
try:
liked_id = self.request.user.books_liked.values("id")
except AttributeError:
qs = Book.objects.all()
else:
qs = Book.objects.annotate(is_liked=Q(id__in=liked_id))        

为了使它工作,我必须创建一个显式的Like模型:

class Like(models.Model):
book = models.ForeignKey(
Book, on_delete=models.CASCADE,
)
user = models.ForeignKey(
User, on_delete=models.CASCADE,
)

去除ManyToManyBook的影响

然后在视图this:

qs = super().get_queryset()
user_likes = Like.objects.filter(
book=OuterRef("pk"),
user=self.request.user
)
return Book.objects.annotate(
is_liked=Exists(user_likes)
)

最新更新