You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django实现认证用户点赞功能遇模板语法错误求助

解决Django用户点赞功能的模板语法错误及逻辑问题

核心问题分析

  1. 模型设计错误:原Post模型的likes是IntegerField,并非关联用户的关系字段,导致视图和模板中调用post.likes.filter()完全无效。
  2. 模板语法限制:Django模板不支持直接调用带参数的方法(如filter(id=...))或链式调用exists(),这是触发TemplateSyntaxError的直接原因。
  3. 视图逻辑冗余:手动维护like_count字段容易出现数据不一致,且单独的Like模型在无额外字段需求时完全多余。

分步修正方案

1. 修正模型(models.py)

替换原likes字段为ManyToManyField,自动关联点赞用户,无需单独的Like模型:

from django.contrib.auth.models import User
from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=255)
    # 需确保Category模型已正确定义,否则Post外键会报错

class Post(models.Model):
    image = models.ImageField(upload_to='posts/', blank=True)
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, blank=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='posts', default='uncategorized')
    post = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    # 关联点赞用户,related_name用于反向查询用户点赞的文章
    liked_by = models.ManyToManyField(User, related_name='liked_posts', blank=True)

2. 修正视图逻辑(views.py)

删除手动维护点赞数的逻辑,直接通过ManyToManyField的count()获取点赞数:

from django.http import JsonResponse, HttpResponseBadRequest
from django.shortcuts import get_object_or_404, render
from django.contrib.auth.decorators import login_required
from .models import Post

def post_list(request):
    posts = Post.objects.all()
    # 提前为每个文章添加是否被当前用户点赞的标记,避免模板中重复查询数据库
    if request.user.is_authenticated:
        for post in posts:
            post.is_liked = request.user in post.liked_by.all()
    else:
        for post in posts:
            post.is_liked = False
    return render(request, 'post_list.html', {'posts': posts})

@login_required
def like_post(request, post_id):
    post = get_object_or_404(Post, pk=post_id)
    if request.method == 'POST':
        user = request.user
        # 切换点赞状态
        if user in post.liked_by.all():
            post.liked_by.remove(user)
        else:
            post.liked_by.add(user)
        # 返回最新点赞数
        return JsonResponse({'like_count': post.liked_by.count()})
    return HttpResponseBadRequest()

3. 修正模板代码(post_list.html)

使用提前赋值的is_liked标记判断状态,避免模板中执行复杂查询:

{% for post in posts %}
<form method="POST" action="{% url 'article:like_post' post.pk %}">
    {% csrf_token %}
    <button class="like-button" data-post-id="{{ post.id }}">
        <i class="fas fa-heart{% if post.is_liked %} liked{% endif %}"></i>
        <span class="like-count">{{ post.liked_by.count }}</span>
    </button>
    <button class="comment-button"><i class="fa-solid fa-comment"></i>5 comments</button>
</form>
{% endfor %}

4. 修正JavaScript代码

添加preventDefault()阻止表单默认提交,确保AJAX请求正常执行:

<script>
$('.like-button').click(function(e){
    e.preventDefault(); // 阻止按钮触发表单提交
    var button = $(this);
    var postId = button.data('post-id');
    $.ajax({
        url: '/like_post/' + postId + '/',
        type: 'POST',
        data: {'csrfmiddlewaretoken': '{{ csrf_token }}'},
        success: function(response){
            button.find('.like-count').text(response.like_count);
            button.find('i.fa-heart').toggleClass('liked');
        }
    });
});
</script>

额外注意事项

  • 如果需要记录点赞时间等额外信息,可保留Like模型,但需设置related_name,并在视图中为每个post添加is_liked标记(不能在模板中直接查询)。
  • 生产环境中建议使用select_related或prefetch_related优化查询性能,避免N+1查询问题。

内容的提问来源于stack exchange,提问作者hypedstan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 20:23:16