如何在Django中按需渲染移动端与桌面端广告以避免JS冲突?
解决Cloudflare缓存下Django项目按需加载广告脚本的方案
方案1:客户端动态加载(纯前端实现,无服务器依赖)
核心是先判断设备类型,再动态创建并插入对应广告的脚本和元素,从根源避免加载不必要的脚本。
- 先写设备检测逻辑:
// 简单的设备判断,可根据需求调整阈值 function isMobile() { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || (window.innerWidth <= 768); }
- 动态生成广告模块:
<!-- 先留一个空容器 --> <div id="ad-container"></div> <script> document.addEventListener('DOMContentLoaded', function() { const container = document.getElementById('ad-container'); const isMobileDevice = isMobile(); // 创建广告外层容器 const adWrapper = document.createElement('div'); adWrapper.className = isMobileDevice ? 'ads-mobile' : 'ads-desktop'; // 创建广告占位元素 const adIns = document.createElement('ins'); adIns.className = 'ee31'; adIns.dataset.zoneid = '68'; adWrapper.appendChild(adIns); // 加载对应广告脚本 const adScript = document.createElement('script'); adScript.async = true; adScript.type = 'application/javascript'; adScript.src = isMobileDevice ? 'https://cdn-ads.com/ad-mobile.js' : 'https://cdn-ads.com/ad-desktop.js'; adWrapper.appendChild(adScript); // 执行广告初始化逻辑 const initScript = document.createElement('script'); initScript.textContent = '(Ads = window.Ads || []).push({"goserve": {}});'; adWrapper.appendChild(initScript); // 把广告模块插入页面 container.appendChild(adWrapper); }); </script>
这个方案完全在用户浏览器端执行,不受Cloudflare缓存影响,每个用户只会加载自己设备对应的脚本。
方案2:Cloudflare边缘检测+分设备缓存(高效推荐)
利用Cloudflare的设备检测能力,在边缘层直接返回对应设备的页面,同时配置分设备缓存,避免缓存冲突。
步骤1:开启Cloudflare设备检测
在Cloudflare控制台的「规则 > 设备检测」中开启功能,开启后Cloudflare会给源站发送CF-Device-Type请求头(值为mobile/desktop),并且可以配置缓存键包含设备类型,让移动端和桌面端拥有独立的缓存版本。
步骤2:Django模板适配请求头
因为缓存是分设备的,所以可以直接在模板里根据Cloudflare的请求头判断设备,只渲染对应广告:
{% if request.META.get('CF-Device-Type') == 'mobile' %} <div class="ads-mobile"> <script async type="application/javascript" src="https://cdn-ads.com/ad-mobile.js"></script> <ins class="ee31" data-zoneid="68"></ins> <script>(Ads = window.Ads || []).push({"goserve": {}});</script> </div> {% else %} <div class="ads-desktop"> <script async type="application/javascript" src="https://cdn-ads.com/ad-desktop.js"></script> <ins class="ee31" data-zoneid="68"></ins> <script>(Ads = window.Ads || []).push({"goserve": {}});</script> </div> {% endif %}
步骤3:配置Cloudflare缓存规则
在「规则 > 缓存规则」里新建规则,设置缓存键为{uri}_{cf-device-type},确保不同设备的页面缓存相互独立,不会出现移动端用户拿到桌面端缓存的情况。
这个方案的优势是页面加载时就只包含对应设备的脚本,比前端动态加载更高效,同时利用Cloudflare的边缘能力,不会增加源站负担。
方案3:Cloudflare Workers修改页面响应(无需改动Django代码)
如果不想修改Django模板,可以用Cloudflare Workers在边缘层直接修改返回的HTML,移除不需要的广告块:
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { const response = await fetch(request); const deviceType = request.headers.get('CF-Device-Type'); // 如果无法获取设备类型或请求失败,直接返回原响应 if (!deviceType || !response.ok) return response; const htmlContent = await response.text(); let modifiedHtml = htmlContent; if (deviceType === 'mobile') { // 移除桌面端广告块(正则匹配整个广告容器) modifiedHtml = modifiedHtml.replace(/<div class="ads-desktop">[\s\S]*?<\/div>/, ''); } else { // 移除移动端广告块 modifiedHtml = modifiedHtml.replace(/<div class="ads-mobile">[\s\S]*?<\/div>/, ''); } // 返回修改后的页面 return new Response(modifiedHtml, { headers: response.headers, status: response.status }); }
同样需要配置分设备缓存规则,确保不同设备拿到的是对应修改后的页面。
内容的提问来源于stack exchange,提问作者Epanadiplose
相关产品推荐
相关产品推荐

