如何修复:TypeError:QuerySet.annotate()接收到非表达式:eqmunir

时间:2019-08-22 21:15:28

标签: python django django-models django-queryset

我在网站上添加了类似功能,用户可以彼此喜欢。

我已成功完成此操作,但是有一个问题。这是在检查用户是否已经喜欢该帖子,这必须在我的HOME视图中专门执行。

这样可以渲染我的主页。为了解决此问题,我在检索帖子时对其执行了.annotate(),并查看用户是否喜欢该帖子。

然后我将其传递到我的主页模板上,并检查用户是否在posts likes属性内。

这是相关代码。

models.py:

class Post(models.Model):
    file = models.ImageField(upload_to='images/')
    summary = models.TextField(max_length=600)
    pub_date = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    likes = models.ManyToManyField(User, through='Like', related_name='likes')

    def __str__(self):
        return self.user.username

    def pub_date_pretty(self):
        return self.pub_date.strftime('%b %e %Y')

    def summary_pretty(self):
        return self.summary[:50]

    @property
    def total_likes(self):
        return self.likes.count()

class Like(models.Model):
    status = models.BooleanField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

views.py:

def home(request):
    posts = Post.objects.all()
    liked_or_not = Post.objects.annotate(likes__user=request.user)
    return render(request, 'posts/home.html', {'posts': posts, 'liked_or_not': liked_or_not})

home.html:

{% if liked_or_not == True %}
      <a href="javascript:{document.getElementById('likepost{{ post.id }}').submit()}"><button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Unlike {{ post.total_likes }} </button></a>
{% else %}
      <a href="javascript:{document.getElementById('likepost{{ post.id }}').submit()}"><button class="btn btn-primary btn-lg btn-block"><span class="oi oi-caret-top"></span> Like {{ post.total_likes }} </button></a>
{% endif %}
<form id="likepost{{ post.id }}" method="POST" action="{% url 'likepost' post.id %}">
  {% csrf_token%}
  <input type="hidden">
</form>

3 个答案:

答案 0 :(得分:1)

对于那些来这里调试错误消息的其他可能性的人,我犯了一个错误,并输入了类似的查询

Like.objects.filter(user=request.user).values('status', flat=True)
# instead of the correct
Like.objects.filter(user=request.user).values_list('status', flat=True)

答案 1 :(得分:1)

我遇到了类似的问题,并使用.annotate解决了
以下是我在models.py

中对Like的定义
class Like(models.Model):
    user = models.ForeignKey(
        "users.User", on_delete=models.CASCADE, related_name="likes"
    )
    writing = models.ForeignKey(
        "writings.Writing", on_delete=models.CASCADE, related_name="likes"
    )

在views.py

    filter_kwargs = {}
    filter_kwargs["writing"] = OuterRef("pk")
    filter_kwargs["user"] = request_user
    subquery = Like.objects.filter(**filter_kwargs)
    writing = (
        Writing.objects.annotate(user_likes=Exists(subquery))
        .get(id=id)
        )

答案 2 :(得分:0)

我不太了解你想做什么。如果要检查用户是否喜欢至少一篇帖子,可以这样进行:

liked_or_not = Like.objects.filter(user=request.user).exists

如果要检查用户是否喜欢特定帖子,可以像这样对其进行点缀:

liked_or_not = Likes.objects.filter(post_id=post_id, user=request.user).exists()

注释的目的不同。它使用提供的查询表达式列表注释QuerySet中的每个对象。表达式可以是简单值,也可以是对模型(或任何相关模型)上字段的引用,也可以是针对与对象中的对象相关的对象计算出的聚合表达式(平均值,总和等)。 QuerySet。在这里https://docs.djangoproject.com/en/2.2/ref/models/querysets/#annotate

了解更多