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

能否以POST方法重定向?Django问答视图实现方案咨询

你的Django答题流程最佳实践问题解析

嘿,咱们一步步来拆解你的问题,帮你理清最佳实践方案:

1. 能不能从add_comment_to_question视图以POST方法重定向?

答案是不行。HTTP协议里的重定向(比如302 Found)默认会让浏览器用GET请求访问目标URL——就算你想通过重定向发送POST,浏览器也会自动转换成GET请求。这是HTTP规范决定的,不存在“POST重定向”这种操作。

2. 原方案的问题&最佳实践建议

你当前的代码里,add_comment_to_question提交评论后重定向到question_detail的GET请求,但这个GET请求只会渲染题目页面(question_detail.html),而用户实际需要回到解题结果页面(question_detail_solution.html),这显然不符合预期。

更重要的是,处理POST请求后直接渲染页面违反了Post/Redirect/Get(PRG)模式——用户刷新页面时会重复提交POST数据,导致评论重复创建或者答题状态异常。

所以最佳方案是拆分视图,让每个视图职责单一:

  • 保留question_detail:只负责展示题目(GET)和处理答题提交(POST),提交后重定向到专门的解题结果视图。
  • 新增question_solution视图:专门负责渲染question_detail_solution.html,展示答题结果、评论表单和已有的评论。
  • add_comment_to_question处理完评论提交后,重定向到question_solution视图,而不是question_detail。

3. 具体代码修改示例

新增question_solution视图

这个视图负责渲染解题结果页面,需要获取答题状态和评论表单:

def question_solution(request, pk):
    question = get_object_or_404(Question, pk=pk)
    user_profile = Profile.objects.get(user=request.user)
    
    # 从URL参数获取之前的答题选择和对错状态
    answer_id = request.GET.get('answer')
    is_correct = request.GET.get('correct') == 'True'
    
    # 额外校验:如果用户已经标记为答对,直接用数据库状态覆盖
    if question in user_profile.solved_questions.all():
        is_correct = True
    
    form = CommentForm()
    # 把该问题的已有评论加进上下文,方便展示
    comments = question.comment_set.all().order_by('-created_date')
    
    context = {
        'question': question,
        'answer': answer_id,
        'correct': is_correct,
        'form': form,
        'comments': comments
    }
    return render(request, 'question_detail_solution.html', context)

修改question_detail的POST逻辑

处理完答题后,不再直接渲染页面,而是重定向到question_solution并带上答题参数:

def question_detail(request, pk):
    question = get_object_or_404(Question, pk=pk)
    user_profile = Profile.objects.get(user=request.user)
    
    if request.method == 'GET':
        context = {'question': question}
        return render(request, 'question_detail.html', context)
    else:
        try:
            answer_id = request.POST['choice']
            answer = question.choice_set.get(id=answer_id)
            is_correct = answer.correct
            
            if is_correct:
                user_profile.solved_questions.add(question)
            
            # 重定向到解题结果页面,传递答题参数
            return redirect('question_solution', pk=pk, answer=answer_id, correct=is_correct)
        except KeyError:
            messages.error(request, "Please make a choice!")
            return render(request, 'question_detail.html', {'question': question})
        except Choice.DoesNotExist:
            messages.error(request, "Invalid choice selected!")
            return render(request, 'question_detail.html', {'question': question})

修改add_comment_to_question的重定向目标

提交评论后,重定向到解题结果页面:

def add_comment_to_question(request, pk):
    question = get_object_or_404(Question, pk=pk)
    if request.method == "POST":
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.question = question
            comment.author = request.user
            comment.save()
            # 重定向到解题结果页面
            return redirect('question_solution', pk=question.id)
    else:
        return HttpResponse("Something went wrong with your request.")

更新URL配置

在urls.py里新增解题结果页面的路由:

from django.urls import path
from . import views

urlpatterns = [
    path('question/<int:pk>/', views.question_detail, name='question_detail'),
    path('question/<int:pk>/solution/', views.question_solution, name='question_solution'),
    # 评论提交的路由(假设你已经配置)
    path('question/<int:pk>/comment/', views.add_comment_to_question, name='add_comment_to_question'),
]

为什么这样做更好?

  • 遵循PRG模式:所有POST请求处理完成后都重定向到GET请求,避免用户刷新页面重复提交数据。
  • 视图职责单一:每个视图只做一件事,代码逻辑更清晰,后续维护和扩展更方便。
  • 流程符合用户预期:答题后到解题页面,提交评论后依然停留在解题页面,体验更顺畅。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:45:18