如何在Django模板中判断当前登录用户是否点赞过帖子?
问题描述
我有如下Django模型结构:
class Post(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) text = models.CharField(max_length=1200, blank=True) class PostLike(models.Model): post = models.ForeignKey(Post, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE)
模板代码片段如下:
{% for post in posts %} ... # 想要在此处判断当前登录用户是否点赞过该帖子,比如: {% if post.userliked %}显示已点赞{% endif %} ... {% endfor %}
我希望在Django模板中判断当前登录用户是否点赞过该帖子,尝试过用post.postlike_set但它返回所有点赞记录,没法直接判断,求可行的解决方法。
解决方法
方法一:在Post模型中添加判断方法
直接在Post模型里新增一个方法,接收当前用户并判断是否存在对应的点赞记录:
class Post(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) text = models.CharField(max_length=1200, blank=True) def is_liked_by(self, user): if user.is_anonymous: return False return PostLike.objects.filter(post=self, user=user).exists()
模板中直接调用该方法:
{% for post in posts %} {% if post.is_liked_by(user) %} <span>已点赞</span> {% else %} <span>未点赞</span> {% endif %} {% endfor %}
注:模板默认可通过user获取当前登录用户,匿名用户会直接返回False。
方法二:视图中预处理帖子列表(避免N+1查询)
如果帖子数量较多,方法一会触发N+1查询(每个帖子单独查询点赞表),性能较差。可以在视图层批量处理:
方式A:用annotate+Exists子查询
from django.db.models import Exists, OuterRef def post_list(request): user = request.user posts = Post.objects.all() if user.is_authenticated: posts = posts.annotate( userliked=Exists( PostLike.objects.filter(post=OuterRef('pk'), user=user) ) ) return render(request, 'post_list.html', {'posts': posts})
模板中直接使用post.userliked判断:
{% for post in posts %} {% if post.userliked %} <span>已点赞</span> {% else %} <span>未点赞</span> {% endif %} {% endfor %}
方式B:批量获取已点赞帖子ID
def post_list(request): user = request.user posts = Post.objects.all() liked_post_ids = [] if user.is_authenticated: liked_post_ids = PostLike.objects.filter(user=user).values_list('post_id', flat=True) # 给每个帖子添加userliked属性 for post in posts: post.userliked = post.id in liked_post_ids return render(request, 'post_list.html', {'posts': posts})
这种方式同样能避免N+1查询,适合不需要复杂ORM操作的场景。
方法三:自定义模板过滤器
创建自定义模板过滤器,直接在模板中判断:
- 在你的app目录下创建
templatetags文件夹,新建post_tags.py文件:
from django import template from .models import PostLike register = template.Library() @register.filter def is_liked(post, user): if user.is_anonymous: return False return PostLike.objects.filter(post=post, user=user).exists()
- 在模板头部加载过滤器:
{% load post_tags %}
- 使用过滤器判断:
{% for post in posts %} {% if post|is_liked:user %} <span>已点赞</span> {% else %} <span>未点赞</span> {% endif %} {% endfor %}
内容的提问来源于stack exchange,提问作者Kachkol Asa
相关产品推荐
相关产品推荐

