英文:
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 == "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
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论