能否以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
相关产品推荐
相关产品推荐

