Django中如何让用户复制到真实链接而非投票跳转URL?
解决Django中右键复制链接获取真实URL的问题
你的核心问题是当前链接的href指向投票跳转接口,导致右键复制时得到的是接口URL而非真实内容链接。可以通过将真实URL放在href中,用JavaScript拦截点击事件完成投票后再跳转的方式解决,具体实现如下:
1. 修改模板中的链接结构
把原来指向投票接口的href替换为真实内容URL,同时用data-*属性存储需要传递给投票接口的item_uid:
{% for c in curated_items %} <div id="itemrow" class="row"> <div class="column"> <div class="row"> <div id="itemtitle" class="column"> <!-- 真实URL放在href,data-item-id存item_uid --> <a href="{{ c.contentitemurl }}" target="_blank" data-item-id="{{ c.contentitemid }}" class="vote-link">{{ c.contentitemtitle }}</a> </div> </div> <div class="row"> <div id="itemmeta" class="column"> <p> <!-- 点赞链接同样用data属性,href设为#避免跳转 --> <a href="#" data-item-id="{{ c.contentitemid }}" class="upvote-link">▲</a> {{c.contentitemsource}}, <i>{{c.contentitemdatepublished}}</i> </p> </div> <div id="itemmeta" class="column"></div> </div> </div> </div> {% empty %} <div class="row"> <div class="column"><p>No objects returned.</p></div> </div> {% endfor %}
2. 添加JavaScript拦截点击事件
通过JS监听链接点击,先发送投票请求,完成后再跳转到真实URL(或刷新页面处理点赞):
// 处理内容链接的投票与跳转 document.querySelectorAll('.vote-link').forEach(link => { link.addEventListener('click', async function(e) { e.preventDefault(); // 阻止默认跳转行为 const itemId = this.dataset.itemId; const targetUrl = this.href; try { // 调用投票接口 await fetch(`/itemclicked/${itemId}`, { method: 'GET' }); // 投票成功后打开真实链接 window.open(targetUrl, '_blank'); } catch (err) { // 即使投票失败,也保证用户能访问内容 window.open(targetUrl, '_blank'); } }); }); // 处理点赞按钮的投票与页面刷新 document.querySelectorAll('.upvote-link').forEach(link => { link.addEventListener('click', async function(e) { e.preventDefault(); const itemId = this.dataset.itemId; try { await fetch(`/upvote/${itemId}`, { method: 'GET' }); // 点赞成功后刷新页面更新计数 window.location.reload(); } catch (err) { console.error('点赞失败:', err); } }); });
3. 可选:改用POST请求提升安全性
如果担心GET请求的安全性(比如重复提交),可以将投票视图改为POST方法:
修改视图函数
from django.views.decorators.http import require_POST @require_POST def ItemClicked(request, item_uid): u = ContentItem.objects.get(contentitemid=item_uid).contentitemurl session_id = request.session.session_key VoteForItem(item_uid, session_id) return JsonResponse({'status': 'ok'}) # 返回JSON而非重定向 @require_POST def ItemUpvote(request, item_uid): session_id = request.session.session_key VoteForItem(item_uid, session_id) return JsonResponse({'status': 'ok'})
更新JavaScript(带上CSRF令牌)
// 获取Django自动生成的CSRF令牌 const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value; // 内容链接处理 document.querySelectorAll('.vote-link').forEach(link => { link.addEventListener('click', async function(e) { e.preventDefault(); const itemId = this.dataset.itemId; const targetUrl = this.href; try { await fetch(`/itemclicked/${itemId}`, { method: 'POST', headers: { 'X-CSRFToken': csrfToken } }); window.open(targetUrl, '_blank'); } catch (err) { window.open(targetUrl, '_blank'); } }); }); // 点赞链接处理 document.querySelectorAll('.upvote-link').forEach(link => { link.addEventListener('click', async function(e) { e.preventDefault(); const itemId = this.dataset.itemId; try { await fetch(`/upvote/${itemId}`, { method: 'POST', headers: { 'X-CSRFToken': csrfToken } }); window.location.reload(); } catch (err) { console.error('点赞失败:', err); } }); });
这种方式既保证了右键复制能获取真实URL,又不影响点击时的投票计数功能,同时可选提升请求安全性。
内容的提问来源于stack exchange,提问作者AlexAntra
相关产品推荐
相关产品推荐

