Django中Ajax POST请求报Method Not Allowed (POST)错误排查
报错根因
Method Not Allowed (POST) 由两个直接原因触发,另外还有3个隐藏bug会导致修复405后功能仍无法正常使用:
- 核心原因1:视图缩进错误
你写的addcomment处理逻辑目前缩进在BlogDetails类内部,和类下的get方法同层级,属于类的内部方法,不是独立的顶层函数视图。但你在路由配置里直接把addcomment当作独立函数绑定到/addcomment/路径,路由根本匹配不到正确的处理逻辑;就算请求误打到BlogDetails类视图,这个类也没有定义post方法处理POST请求,会直接返回405。 - 核心原因2:请求方法判断大小写错误
就算把addcomment移出类成为独立视图,你写的判断if request.method == 'post':也永远不会生效——Django里request.method返回的HTTP方法名是全大写格式,POST请求对应的值是'POST',小写判断会直接跳过所有请求处理逻辑,函数没有返回任何有效响应时Django默认抛出405。 - 隐藏bug1:Ajax回调拼写错误
代码里写的sucess少了一个字母c,正确拼写是success,后端正常返回数据时前端不会执行插入评论的逻辑。 - 隐藏bug2:JS引号语法错误
代码里var placement = "commentform"、button=="newcommentform"、var placement = "newcommentform"三处的字符串引号不配对,会直接触发JS语法错误,导致Ajax请求根本发不出去。 - 隐藏bug3:视图缺少异常返回
addcomment视图没有处理GET请求、表单校验不通过的场景,命中这些场景时没有合法返回值,会触发500或405错误。
修复步骤
1. 修正views.py
把addcomment顶格写,放到BlogDetails类外面成为独立视图,修正方法判断的大小写,补全异常分支返回:
class BlogDetails(View): def get(self, request, blog_id): query = request.GET.get('query') if query: return redirect(reverse('website:search') + '?query=' + query) blog = Blog.objects.get(id=blog_id) total_comment = Comment.objects.filter(blog=blog).count() allcomments = blog.comments.filter(status=True) blog_list = Blog.objects.all() comment_form = NewCommentForm() data = { 'blog': blog, 'blog_list': blog_list, 'total_comment': total_comment, 'comment_form': comment_form, 'allcomments': allcomments } return render(request, "blog_detail.html", data) # 注意:此处必须顶格,和BlogDetails类保持同级 def addcomment(request): # 修正为全大写POST if request.method == 'POST': comment_form = NewCommentForm(request.POST) if comment_form.is_valid(): user_comment = comment_form.save(commit=False) user_comment.user = request.user user_comment.save() result = comment_form.cleaned_data.get('content') user = request.user.username return JsonResponse({'result': result, 'user': user}) # 表单校验失败返回 return JsonResponse({'error': '评论内容不合法'}, status=400) # 非POST请求返回 return JsonResponse({'error': '不支持该请求方法'}, status=405)
2. 修正前端Ajax代码
修正拼写错误、引号语法错误:
$(document).on('click','#newcomment',function(e){ e.preventDefault(); var button = $(this).attr("value"); var placement = "commentform"; if (button == "newcommentform"){ placement = "newcommentform"; } $.ajax({ type: 'POST', url: '{% url "website:addcomment" %}', data: $("#" + button).serialize(), cache: false, // 修正success拼写 success: function(json){ console.log(json) $('<div class="my-2 p-2" style="border: 1px solid grey"> \ <div class="d-flex justify-content-between">By ' + json['user'] + '<div></div>Posted: Just now!</div> \ <div>' + json['result'] + '</div> \ <hr> \ </div>').insertBefore('#' + placement); }, error: function(xhr){ console.log(xhr.responseText) } }); })
3. 确认路由配置
当前路由写法本身没有问题,只要确保urls.py中导入的addcomment是修正后的顶层视图函数即可:
path('blog/<int:blog_id>', BlogDetails.as_view(), name="blog_detail"), path('addcomment/', addcomment, name="addcomment"),
内容的提问来源于stack exchange,提问作者Bibek Karna
相关产品推荐
相关产品推荐

