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

Django仿Quora应用点赞功能及按钮显示问题求助

嘿,我来帮你解决这个Quora仿站的点赞按钮问题!你现在遇到的两个核心问题:一是多用户点赞时会同时出现Upvote和Downvote按钮,二是没法高效判断当前用户是否给答案点过赞。咱们一步步来修复:

解决方案步骤

1. 先给Upvote模型加唯一约束(避免重复点赞)

首先修改models.py里的Upvote模型,加上唯一约束,确保一个用户不能给同一个答案多次点赞,同时补全Django要求的on_delete参数:

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

class Question(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length=200, blank=True, null=True)
    description = models.TextField()
    pub_date = models.DateTimeField()

    def __str__(self):
        return self.title

class Answer(models.Model):
    answer_text = models.TextField()
    questions = models.ForeignKey(Question, on_delete=models.CASCADE)
    pub_date = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.answer_text

    def get_absolute_url(self):
        return reverse('answer:answer_by_me', kwargs={'pk': self.user.id})

class Upvote(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    answers = models.ForeignKey(Answer, on_delete=models.CASCADE)

    # 新增唯一约束,防止重复点赞
    class Meta:
        unique_together = ('user', 'answers')

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

2. 在Answer模型里添加判断用户点赞状态的方法

在Answer类里加一个便捷方法,让模板能直接判断当前用户是否给该答案点过赞:

class Answer(models.Model):
    # (保留原有字段和方法)

    # 新增方法:判断指定用户是否给该答案点过赞
    def has_upvoted(self, user):
        if not user.is_authenticated:
            return False
        return self.upvote_set.filter(user=user).exists()

3. 重构模板逻辑,去掉多余循环

原来的模板遍历所有点赞记录是错误的,我们直接用上面的方法判断用户状态,只渲染一个对应按钮:

{% extends 'base.html' %} 

{% block title %} {{ question.title }} {% endblock %} 

{% block body %}
<h3><i>{{ question.title }}</i></h3>
{{ question.description }}

{% for answer in question.answer_set.all %}
<br>
<div>
    <p>{{ answer.answer_text }} 
        <span style="font-size: 15px">by [{{ answer.user }}]</span>
    </p>
    <form method="post" action="{% url 'answer:detail' question.id %}">
        {% csrf_token %}
        <input type="hidden" name="type" value="vote">
        <input type="hidden" name="answer_id" value="{{ answer.id }}">
        
        {% if user.is_authenticated %}
            {% if answer.has_upvoted(user) %}
                <!-- 用户已点赞,显示取消点赞按钮 -->
                <input type="submit" class="btn btn-sm btn-warning" value="Downvote|{{ answer.upvote_set.count }}">
            {% else %}
                <!-- 用户未点赞,显示点赞按钮 -->
                <input type="submit" class="btn btn-sm btn-success" value="Upvote|{{ answer.upvote_set.count }}">
            {% endif %}
        {% else %}
            <!-- 用户未登录,显示禁用按钮提示 -->
            <button class="btn btn-sm btn-secondary" disabled>请登录点赞|{{ answer.upvote_set.count }}</button>
        {% endif %}
    </form>
</div>
{% endfor %}
{% endblock %}

4. 优化查询性能(可选但推荐)

为了避免模板中每个答案调用has_upvoted时产生N+1数据库查询,我们可以在DetailView里提前预加载数据并标记点赞状态:

from django.views.generic import DetailView
from .models import Question, Upvote

class QuestionDetailView(DetailView):
    model = Question
    template_name = '你的模板路径.html'  # 替换为实际模板路径

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        question = self.get_object()
        # 提前预加载所有答案及关联的点赞记录
        answers = question.answer_set.all().prefetch_related('upvote_set')
        
        if self.request.user.is_authenticated:
            # 获取当前用户点赞过的所有答案ID
            user_upvoted_ids = Upvote.objects.filter(user=self.request.user).values_list('answers__id', flat=True)
            # 给每个答案添加is_upvoted属性
            for answer in answers:
                answer.is_upvoted = answer.id in user_upvoted_ids
        
        context['answers'] = answers
        return context

之后模板里就可以用answer.is_upvoted代替answer.has_upvoted(user),进一步提升页面加载速度。

这样修改后,每个答案只会显示一个对应状态的按钮,总票数也能正确统计,完美解决你遇到的问题!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:40:21