Django模板标签URL在JavaScript中失效,动态添加按钮报错
解决Django中JS动态生成链接时模板标签未解析的404问题
问题核心原因
Django的模板标签(如{% url %}、{% static %})仅在服务器渲染模板阶段被解析执行,而你的JavaScript代码是在客户端浏览器中运行的,直接在JS字符串中写入模板标签不会被服务器处理,最终生成的URL是原始的标签文本(比如{% url 'expense-edit' expense.id %}),导致浏览器请求无效路径触发404错误。
解决方案(两种常用方案)
方案1:模板预渲染URL模板,传递给JS使用
在HTML模板中提前用Django标签解析出URL的模板格式,存入全局JS变量,再在JS中替换动态ID:
- 在页面模板(如
expenses.html)中,引入JS之前添加以下代码:
<script> // 预渲染URL模板和静态资源路径 window.expenseConfig = { editUrlTemplate: "{% url 'expense-edit' 0 %}".replace('0', '{id}'), deleteUrlTemplate: "{% url 'expense-delete' 0 %}".replace('0', '{id}'), deleteImageUrl: "{% static 'img/delete.png' %}" }; </script>
这里用0作为占位符,后续在JS中替换为实际的item.id。
- 修改JS中的表格行生成逻辑:
data.forEach((item) => { const editUrl = expenseConfig.editUrlTemplate.replace('{id}', item.id); const deleteUrl = expenseConfig.deleteUrlTemplate.replace('{id}', item.id); tbody.innerHTML += ` <tr> <td>${item.amount}</td> <td>${item.category}</td> <td>${item.description}</td> <td>${item.date}</td> <td> <a href="${editUrl}" class="btn btn-secondary btn-sm">Edit</a> <a href="${deleteUrl}"> <img src="${expenseConfig.deleteImageUrl}" width="35" height="35"/> </a> </td> </tr>`; });
方案2:后端API直接返回完整URL
修改search_expenses视图,在返回的每条数据中直接携带解析好的编辑、删除URL和图片路径:
- 在
views.py的search_expenses函数中扩展返回数据:
from django.urls import reverse from django.templatetags.static import static def search_expenses(request): # 原有查询逻辑... expenses = Expense.objects.filter(...) # 构造包含URL的返回数据 data = [] for expense in expenses: data.append({ 'amount': expense.amount, 'category': expense.category, 'description': expense.description, 'date': expense.date.strftime('%Y-%m-%d'), 'edit_url': reverse('expense-edit', args=[expense.id]), 'delete_url': reverse('expense-delete', args=[expense.id]), 'delete_image_url': static('img/delete.png') }) return JsonResponse(data, safe=False)
- 修改JS代码直接使用返回的URL字段:
data.forEach((item) => { tbody.innerHTML += ` <tr> <td>${item.amount}</td> <td>${item.category}</td> <td>${item.description}</td> <td>${item.date}</td> <td> <a href="${item.edit_url}" class="btn btn-secondary btn-sm">Edit</a> <a href="${item.delete_url}"> <img src="${item.delete_image_url}" width="35" height="35"/> </a> </td> </tr>`; });
额外优化建议
当前fetch请求使用POST方法并加了csrf_exempt,生产环境建议移除csrf_exempt,并在请求中携带CSRF Token:
fetch("http://127.0.0.1:8000/search-expenses", { body: JSON.stringify({ searchText: searchValue }), method: "POST", headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, 'Content-Type': 'application/json' } })
内容的提问来源于stack exchange,提问作者Kratos
相关产品推荐
相关产品推荐

