调用Django重定向视图时,如何用Fetch API实现页面跳转?
Django Fetch API 重定向不生效问题解决方案
问题描述
我有如下Django重定向视图:
def remove_from_cart(request, product_id): product = Product.objects.get(pk=product_id) cart = Cart(request) cart.remove_product(product) cart.save() message = Message(request) message.set(f'{product.name} has been removed from cart!') return redirect('shopping:cart')
我尝试通过Fetch API跳转到该视图响应的URL,代码如下:
remove.addEventListener('click', e => { let url = "{% url 'shopping:remove_from_cart' 123 %}".replace('123', e.target.id) fetch(url, { redirect: 'follow', }) .then(response => console.log(response.status)) // 日志输出200 })
但页面并未发生重定向,不过手动输入该URL时功能正常。请问该如何修正这个问题?
解决方案
这是个很常见的Fetch API使用误区哦——Fetch的redirect: 'follow'只是让它跟随HTTP重定向获取最终的响应内容,但并不会触发浏览器的页面跳转行为。手动访问URL时浏览器会自动处理重定向,但Fetch是在JS层面发起请求,完全不会影响当前页面的导航状态。
你可以通过下面两种方式解决:
方式1:直接用浏览器跳转代替Fetch
既然你不需要处理响应数据,只是想触发后端逻辑并跳转,那完全没必要用Fetch,直接让浏览器导航到目标URL就行:
remove.addEventListener('click', e => { let url = "{% url 'shopping:remove_from_cart' 123 %}".replace('123', e.target.id) window.location.href = url; })
方式2:通过Fetch获取重定向目标后手动跳转
如果你确实需要用Fetch(比如要先处理一些响应数据),可以从响应头里拿到重定向的目标URL,然后手动触发页面跳转:
remove.addEventListener('click', e => { let url = "{% url 'shopping:remove_from_cart' 123 %}".replace('123', e.target.id) fetch(url, { redirect: 'manual' }) // 这里用manual不自动跟随重定向 .then(response => { const redirectUrl = response.headers.get('Location'); if (redirectUrl) { window.location.href = redirectUrl; } }) })
额外建议:用POST请求处理删除操作(更规范)
建议删除类操作使用POST请求而非GET,这样更符合Web开发的REST规范,也能避免一些安全问题。此时需要给请求带上CSRF令牌,示例代码如下:
remove.addEventListener('click', e => { let url = "{% url 'shopping:remove_from_cart' 123 %}".replace('123', e.target.id) fetch(url, { method: 'POST', headers: { 'X-CSRFToken': getCookie('csrftoken') // 需要获取CSRF令牌 } }) .then(response => { const redirectUrl = response.headers.get('Location'); if (redirectUrl) { window.location.href = redirectUrl; } }) }) // 辅助函数:从Cookie中获取CSRF令牌 function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; }
内容的提问来源于stack exchange,提问作者barciewicz
相关产品推荐
相关产品推荐

