【问题标题】:Marking only one answer as accepted仅将一个答案标记为已接受
【发布时间】:2026-01-28 19:30:01
【问题描述】:

我正在构建一个简单的问答网站,例如 Stack Overflow,并且正在构建将答案标记为已接受,但是当我实施它时,它会将每个答案都标记为已接受。我的意思是用户可以接受任何答案,但我不想要这个。我正在尝试制作 - 用户只能标记一个已接受的答案。如果用户将一个答案标记为已接受并尝试将第二个答案标记为已接受,则第一个将被删除,第二个将被标记

models.py

class Answer(models.Model):
    answer_user = models.ForeignKey(User,on_delete=models.CASCADE)
    body = models.CharField(max_length=30,null=True)
    accepted = models.BooleanField(default=False)

views.py

def mark_accepted(request, question_id):
    post = get_object_or_404(Answer, pk=question_id)

    if request.GET.get('submit') == 'accept':
        if post.accepted == True:
            post.accepted = False
        else:
            post.accepted = True
    
    return JsonResponse({'action':'accept'})

【问题讨论】:

  • @DecapitatedSoul 接受端点似乎只知道哪个问题,而不是哪个答案,因此尽管考虑到 OP 的要求,这没有意义,但它可能 is 每个答案都被接受.
  • 我不确定我的评论去了哪里,但问题似乎是你已经确定了答案是否被接受为 answer 的属性,所以每个人都可以单独接受或不接受,而如果要求是“一个问题可以有零个或恰好一个接受的答案”,那么使得哪个答案已被接受,则 question 的属性将适合好多了。

标签: python html django ajax django-views


【解决方案1】:

这就是我的做法。

首先,您的Answer 模型应该与Question 模型具有 ForeignKey 关系。

这样

class Answer(models.Model):
    answer_user = models.ForeignKey(User,on_delete=models.CASCADE)
    body = models.CharField(max_length=30,null=True)
    accepted = models.BooleanField(default=False)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)

您还应该在mark_as_accepted 视图中传入ans_id,以唯一标识应标记为已接受的当前答案。

在你看来,

  • 查询 Answer 模型并获得之前接受的答案(如果有)。叫它prev_accepted_ans

    prev_accepted_ans = Answer.objects.filter(question=question_id, accepted=True)

  • 在您认为的 else 条件中,您必须将先前接受的答案 (prev_accepted_ans) 的接受属性标记为 False。

    prev_accepted_ans.update(accepted=False)

def mark_accepted(request, question_id, ans_id):
    # Get the previously accepted answer (if any).
    prev_accepted_ans = Answer.objects.filter(question=question_id, accepted=True)
    
    # Get the answer that should be marked as accepted.
    post = get_object_or_404(Answer, id=ans_id)

    if request.GET.get('submit') == 'accept':
        if post.accepted == True:
            post.accepted = False
        else:
            # Mark the accepted attribute of prev_accepted_ans as False
            prev_accepted_ans.update(accepted=False)

            post.accepted = True
    
    return JsonResponse({'action':'accept'})

【讨论】:

    【解决方案2】:

    首先,您的端点需要两个参数:question_id 和 answer_id。

    其次,在通过 answer_id 成功检索到答案后,应首先将所有 question_id=question_id 和accepted=true 的记录的所有接受字段更新为false;那么您应该将 question_id=question_id 和 answer_id=answer_id 的记录的接受字段更新为 true。

    注意:Answer 模型需要 FK(question)to Question 模型。它的PK是answer_id。

    【讨论】:

    • 感谢您的建议,我也有一个FKQuestion 模型但是我将如何防止用户只能标记一个接受答案?
    • 如果您希望每个问题只有一个接受的答案,您需要实现我的答案的第二部分。您应该将其他答案的接受字段更新为 false,并将当前答案(您检索到的答案)的接受字段更新为 true。这样,问题总是有一个接受=真的答案。
    【解决方案3】:

    我认为最简单的方法是向 Question 模型本身添加accepted_answer 字段!

    class Answer(models.Model):
        answer_user = models.ForeignKey(User,on_delete=models.CASCADE)
        body = models.CharField(max_length=30,null=True)
    
    class Question(models.Model):
        ...
        accepted_answer = models.ForeignKey(Answer, on_delete=models.SET_NULL, null=True, blank=True)
    

    现在您只需要更改 Question 模型中的 accepted_answer 即可,一切都会好起来的!

    【讨论】:

      最近更新 更多