在Django中,我如何检查一个对象是否存在于多对多关系中?

huangapple go评论79阅读模式
英文:

django : How can i check if an object is exist in a many-to-many relation?

问题

我有一个名为Post的模型其字段如下

class Post(models.Model):
    title = models.CharField(max_length=500)
    slug = models.SlugField(allow_unicode=True, unique=True, null=True, blank=True)
    likes = models.ManyToManyField(User, blank=True, help_text="喜欢的数量")
    likes_count = models.IntegerField(default=0, help_text="喜欢的数量")

    def __str__(self):
        return self.title

我有一个视图需要检查用户是否在喜欢关系中并进行一些操作但我不知道该怎么做这是我的视图

def Like_view(request, slug):
    post = get_object_or_404(Post, slug=slug)
    if not request.user in post.likes:
        post.likes.add(request.user)
        post.likes_count += 1
        post.save()
    else:
        post.likes.remove(request.user)
        post.likes_count -= 1
        post.save()
英文:

I have a model named Post that has some fields like this :

class Post(models.Model):
    title = models.CharField(max_length=500)
    slug = models.SlugField(allow_unicode=True , unique=True , null=True , blank=True)
    likes = models.ManyToManyField(User , blank=True , help_text="amount of likes")
    likes_count = models.IntegerField(default=0 , help_text="amount of likes")

    def __str__(self):
        return self.title

and I have a view that needs to check if the user is in "likes" relation and do some stuff . But I don't know what to do ! this is my view:

def Like_view(request , slug):
    post = get_object_or_404(Post , slug=slug)
    if not request.user in post.likes:
        post.likes.add(request.user)
        post.likes_count += 1
        post.save()
    else:
        post.likes.remove(request.user)
        post.likes_count -= 1
        post.save()

答案1

得分: 2

你不需要保存点赞数量。

在你的情况下:

likes_count = post.likes.count()
# 或者
likes_count = post.likes.aggregate(likes_count=Count('*')).get('likes_count')

有关更多信息,请查看这里:
https://docs.djangoproject.com/en/4.2/ref/models/querysets/#aggregation-functions

对于你的视图,我更喜欢在返回为空时删除点赞,这意味着你没有点赞,可以创建它:

def Like_view(request, slug):
    if not Post.likes.through.objects.filter(post__slug=slug, user=post.user).delete():
        get_object_or_404(Post, slug=slug).likes.add(request.user)

在我看来,模式可以更好,通过在中间模型中使用布尔复选框。在这种情况下,你只需进行一次数据库调用:

Post.likes.through.objects.filter(post__slug=slug, user=post.user).update(is_like=Q(is_like=False))
英文:

you dont need to save count of likes.

in your case:

likes_count = post.likes.count()
# or 
likes_count = post.likes.aggregate(likes_count=Count('*')).get('likes_count')

more here:

https://docs.djangoproject.com/en/4.2/ref/models/querysets/#aggregation-functions

For your view I prefer to delete like, if returns nothing - it means you don't have a like and you can create it:

def Like_view(request , slug):
    if not Post.likes.through.objects.filter(post__slug=slug, user = post.user).delete():
        get_object_or_404(Post , slug=slug).likes.add(request.user)

And my opinion, the sheme can be better, with boolean checkbox in through model. In this case you can do only one DB call:

Post.likes.through.objects.filter(post__slug=slug, user = post.user).update(is_like=Q(is_like=False))

答案2

得分: 2

models.py

# 在反向关系中,你还可以为其添加一个[related name][1]:

class Post(models.Model):
    title = ...
    slug = ...
    likes = models.ManyToManyField(
        User, blank=True, help_text="点赞数量", related_name="likes"
    )
    likes_count = ...

views.py

# views.py

def like_view(request, slug):
    post = get_object_or_404(Post, slug=slug)
    user_likes = request.user.likes.all()
    liked = True if post in user_likes else False

    if request.method == "POST":
        if liked:
            request.user.likes.remove(post)
            post.likes_count -= 1
            post.save()
        else:
            request.user.likes.add(post)
            post.likes_count += 1
            post.save()
        return redirect(reverse("like-view", kwargs={"slug": post.slug}))

    context = {"post": post, "liked": liked}

    return render(request, "post_detail.html", context)

urls.py

# urls.py

urlpatterns = [
    path('post/<slug:slug>', like_view, name='like-view')
]

post_detail.html

<!-- post_detail.html -->

<!DOCTYPE html>
<html lang="en">
    <body>
        <form action="{% url 'like-view' post.slug %}" method="post" >
            {% csrf_token %}
            {% if liked %}
            <button type="submit">取消点赞</button>
            {% else %}
            <button type="submit">点赞</button>
            {% endif %}
        </form>
    </body>
</html>

<details>
<summary>英文:</summary>

You can also add a [related name][1] for backward relation:

models.py

class Post(models.Model):
title = ...
slug = ...
likes = models.ManyToManyField(
User, blank=True, help_text="amount of likes", related_name="likes"
)
likes_count = ...


views.py

def like_view(request, slug):
post = get_object_or_404(Post, slug=slug)
user_likes = request.user.likes.all()
liked = True if post in user_likes else False

if request.method == &quot;POST&quot;:
    if liked:
        request.user.likes.remove(post)
        post.likes_count -= 1
        post.save()
    else:
        request.user.likes.add(post)
        post.likes_count += 1
        post.save()
    return redirect(reverse(&quot;like-view&quot;, kwargs={&quot;slug&quot;: post.slug}))

context = {&quot;post&quot;: post, &quot;liked&quot;: liked}

return render(request, &quot;post_detail.html&quot;, context)

urls.py

urlpatterns = [
path('post/<slug:slug>', like_view, name='like-view')
]


post_detail.html

<!DOCTYPE html>
<html lang="en">
<body>
<form action="{% url 'like-view' post.slug %}" method="post" >
{% csrf_token %}
{% if liked %}
<button type="submit">Unlike</button>
{% else %}
<button type="submit">Like</button>
{% endif %}
</form>
</body>
</html>


  [1]: https://docs.djangoproject.com/en/4.2/ref/models/fields/#django.db.models.ForeignKey.related_name

</details>



# 答案3
**得分**: 0

我不要翻译的部分:

    def Like_view(request , slug):
        post = get_object_or_404(Post , slug=slug)
        if not post.likes.filter(id = request.user.id).exists():
            post.likes.add(request.user)
            post.likes_count += 1
            post.save()
        else:
            post.likes.remove(request.user)
            post.likes_count -= 1
            post.save()

<details>
<summary>英文:</summary>

I had to edit the view like this :

    def Like_view(request , slug):
        post = get_object_or_404(Post , slug=slug)
        if not post.likes.filter(id = request.user.id).exists():
            post.likes.add(request.user)
            post.likes_count += 1
            post.save()
        else:
            post.likes.remove(request.user)
            post.likes_count -= 1
            post.save()

</details>



huangapple
  • 本文由 发表于 2023年6月15日 02:57:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76476756.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定