Django中POST请求访问删除路由报404,GET可正常访问的问题排查
问题
点击deleteSubmit按钮通过路由saga/delete/2删除阵营时,返回404错误:
"POST /saga/delete/2/ HTTP/1.1" 404 3048 Not Found: /saga/delete/2/
但手动用GET方法访问该路由可正常访问。
相关配置代码
项目URL配置(project/urls.py)
urlpatterns = [ path("saga/", include("saga.urls")), path('admin/', admin.site.urls), ]
应用URL配置(saga/urls.py)
app_name = "saga" urlpatterns = [ #ex: /saga/ path("", views.index, name = "index"), #ex: /saga/results/1 path("results/<int:factionId>",views.results, name = 'results'), #ex: /saga/edit/ path("create/", views.create, name = 'create'), #ex: /saga/edit/1 path("edit/<int:factionId>", views.edit, name = 'edit'), #ex: /saga/delete/1 path("delete/<int:factionId>", views.delete, name = 'delete') #ex: /saga/edit/push/? ]
表单提交JS代码
factionForm.addEventListener('submit', function(event) { //prevent the default form submission event.preventDefault(); //If the Save Changes button is clicked if (event.submitter === saveSubmit){ console.log("Save Changes Pressed"); // Code to handle form submission and save changes to the database } //Otherwise if the Delete changes button is clicked else if(event.submitter === deleteSubmit){ console.log("Delete Faction Pressed"); //Attempt to send data to server fetch(`/saga/delete/${factionId.value}/`, { method: 'POST', headers: { 'X-CSRFToken': getCSRF(), }, }) //Get response from server .then(response => { if (response.ok) { console.log('Faction deleted successfully'); } else { //If a problem occurred display the response console.error('Error deleting faction',response); } }) //If There is an error output it .catch(error => { console.error('Error:', error); }); } //Otherwise if neither approved button submitted the form something went wrong else { console.log(event.submitter, "somehow submitted the form, check and correct the code near that element"); } })
CSRF获取函数
function getCSRF() { const cookies = document.cookie.split('; '); for (let i = 0; i < cookies.length; i++) { const [name, value] = cookies[i].split('='); if (name === "csrfToken") { return decodeURIComponent(value); } } return null; }
视图函数(saga/views.py)
def delete(request,factionId): #Get Faction To Delete faction = Faction.objects.filter(id = factionId) #If Faction Exists and Data has been posted from a form if faction.count() > 0 and request.method == 'POST': #Delete the faction faction.delete() #Return to create page on success (Will change to success message later) return redirect(reverse("saga:create")) #Return to home page on failure (happens currently during a Get request return redirect(reverse("saga:index"))
表单定义
<form id = "factionForm" method = "post"> {% csrf_token %} <!-- Lots of Code --> </form>
已尝试移除csrf_token并使用@csrf_exempt装饰器、更换csrf_token获取函数、确认CsrfViewMiddleware存在、修改URL配置,但问题未解决。
解决方案
1. 修复URL路径的斜杠匹配问题
Django的path()是严格匹配路径的,你的URL配置中delete/<int:factionId>不带末尾斜杠,但JS中fetch的URL是/saga/delete/${factionId.value}/(带末尾斜杠),导致POST请求路径无法匹配路由,返回404。
修改方法二选一:
- 方法一:修改JS中的fetch URL,去掉末尾斜杠:
fetch(`/saga/delete/${factionId.value}`, { // 其他配置不变 }) - 方法二:修改saga/urls.py中的路由,添加末尾斜杠:
path("delete/<int:factionId>/", views.delete, name = 'delete')
2. 修复CSRF Token的Cookie名称
Django默认存储CSRF Token的Cookie名称是csrftoken(全小写),但你的getCSRF()函数中判断的是"csrfToken"(驼峰式),导致无法正确获取Token,即使URL匹配成功,也会触发CSRF验证失败。
修改getCSRF()函数:
function getCSRF() { const cookies = document.cookie.split('; '); for (let i = 0; i < cookies.length; i++) { const [name, value] = cookies[i].split('='); // 改为全小写的csrftoken if (name === "csrftoken") { return decodeURIComponent(value); } } return null; }
3. 可选优化:使用Django的URL反向解析
为避免硬编码URL导致的路径错误,建议在模板中生成删除接口的URL,传递给JS使用:
<script> const deleteUrl = "{% url 'saga:delete' faction.id %}"; </script>
之后在JS中直接使用deleteUrl作为fetch的地址,无需手动拼接路径。
内容的提问来源于stack exchange,提问作者Scott Field
相关产品推荐
相关产品推荐

