Django DetailView页面提交表单遇405 Method Not Allowed错误求助
Django表单提交405 Method Not Allowed问题解决
问题根源
你遇到的405错误是因为:
- 表单未指定
action属性,默认提交到当前DetailView的URL,但DetailView默认仅支持GET请求,不处理POST方法 - 你编写的
get_score处理视图,要么未配置对应的URL路由,要么表单没指向该视图的地址
解决方案一:单独使用处理视图
1. 配置URL路由
在urls.py中添加get_score的路由,同时传递赛事ID(用于处理完分数后重定向回详情页):
from django.urls import path from .views import TournamentDetailView, get_score urlpatterns = [ path('tournament/<int:pk>/', TournamentDetailView.as_view(), name='tournament-detail'), path('tournament/<int:pk>/submit-score/', get_score, name='submit-score'), ]
2. 修改表单HTML
指定表单提交的action为上述路由,同时添加隐藏字段传递选手ID(以便处理分数时关联到对应选手):
<h7><img style="width:2rem; height:2rem" src="{{ player.avatar.url }}"> {{player}}</h7> <form method="POST" action="{% url 'submit-score' tournament.pk %}"> {% csrf_token %} <input type="hidden" name="player_id" value="{{ player.id }}"> <input style="width:2rem" type="text" id="{{player}}" name="score"> <input type="submit" value="OK"> </form> {{ val }}
注:tournament.pk需替换为你模板中实际的赛事对象变量名
3. 完善get_score视图
处理分数逻辑,并在完成后重定向回详情页:
from django.shortcuts import render, redirect, get_object_or_404 from .forms import GetScoreForm from .models import Player, Tournament def get_score(request, pk): tournament = get_object_or_404(Tournament, pk=pk) if request.method == 'POST': form = GetScoreForm(request.POST) if form.is_valid(): score_val = form.cleaned_data.get("score") player_id = request.POST.get('player_id') player = get_object_or_404(Player, id=player_id) # 在这里编写你的分数处理逻辑,比如保存到数据库 # player.score = score_val # player.save() # 处理完成后重定向回赛事详情页 return redirect('tournament-detail', pk=pk) else: form = GetScoreForm() return render(request, 'tournamentdetailview.html', {'form': form, 'tournament': tournament})
解决方案二:在DetailView中直接处理POST请求
无需额外创建视图,直接在DetailView类中重写post方法:
1. 修改DetailView类
from django.views.generic.detail import DetailView from django.shortcuts import get_object_or_404 from .models import Tournament, Player from .forms import GetScoreForm class TournamentDetailView(DetailView): model = Tournament template_name = 'tournamentdetailview.html' # 把表单加入上下文,供模板调用 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['form'] = GetScoreForm() return context # 重写post方法处理表单提交 def post(self, request, *args, **kwargs): self.object = self.get_object() form = GetScoreForm(request.POST) if form.is_valid(): score_val = form.cleaned_data.get("score") player_id = request.POST.get('player_id') player = get_object_or_404(Player, id=player_id) # 编写分数处理逻辑 # player.score = score_val # player.save() # 重定向回当前页面,避免重复提交 return self.get(request, *args, **kwargs) # 表单验证失败时,返回页面并携带错误表单 context = self.get_context_data(**kwargs) context['form'] = form return self.render_to_response(context)
2. 调整表单HTML
此时表单无需指定action,默认提交到当前DetailView的URL,只需保留隐藏字段传递选手ID:
<h7><img style="width:2rem; height:2rem" src="{{ player.avatar.url }}"> {{player}}</h7> <form method="POST"> {% csrf_token %} <input type="hidden" name="player_id" value="{{ player.id }}"> <input style="width:2rem" type="text" id="{{player}}" name="score"> <input type="submit" value="OK"> </form> {{ val }}
内容的提问来源于stack exchange,提问作者Wiktor Malinowski
相关产品推荐
相关产品推荐

