You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 在页面模板(如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。

  1. 修改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和图片路径:

  1. 在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)
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:45:34