如何将Django视图/模板数据传入静态JavaScript文件?
解决方案:无需嵌入整个JS文件传递Django模型数据到maps.js
你的问题核心在于:maps.js里的locations变量是自执行函数的局部变量,外部提前定义的同名变量无法被它访问。下面是几个更优雅的解决思路,不用把上万行JS塞进模板:
方案1:暴露全局数据,修改maps.js读取全局变量
首先在模板中把Django模型数据渲染成全局变量,然后调整maps.js从全局变量获取数据:
模板代码(template.html)
<!-- 先渲染Django模型数据为全局变量 --> <script> // 使用window对象确保全局可访问 window.mapLocations = [ {% for model in query_list %} [ locationData( 'link_to', 'img_url', '{{ model.name|escapejs }}', '{{ model.address|escapejs }}', '5', '10' ), {{ model.latitude }}, {{ model.longitude }}, {{ forloop.counter }}, '{{ model.icon|escapejs }}' ]{% if not forloop.last %},{% endif %} {% endfor %} ]; </script> <!-- 加载原maps.js文件 --> <script type="text/javascript" src="{% static 'base/scripts/maps.js' %}"></script>
修改maps.js代码
把原来硬编码的locations数组替换为读取全局变量(保留默认值作为 fallback):
(function($){ "use strict"; function mainMap() { var ib = new InfoBox(); // Infobox Output function locationData(locationURL,locationImg,locationTitle, locationAddress, locationRating, locationRatingCounter) { return('SOME_HTML_WITH_VARIABLES') } // Locations - 优先使用全局传入的数据,没有则用默认值 var locations = window.mapLocations || [ [ locationData('listings-single-page.html','images/listing-item-01.jpg',"Tom's Restaurant",'964 School Street, New York', '3.5', '12'), 40.94401669296697, -74.16938781738281, 1, '<i class="im im-icon-Chef-Hat"></i>'], ]; // ... 后续地图初始化逻辑 ... } mainMap(); })(jQuery);
方案2:通过DOM data属性传递数据
把数据挂载到隐藏的DOM元素上,让maps.js从DOM读取数据,无需修改全局变量:
模板代码(template.html)
<!-- 隐藏的DOM元素,存储地图数据 --> <div id="map-data" style="display: none" data-locations='[ {% for model in query_list %} [ "{{ model.name|escapejs }}", "{{ model.address|escapejs }}", {{ model.latitude }}, {{ model.longitude }}, {{ forloop.counter }}, "{{ model.icon|escapejs }}" ]{% if not forloop.last %},{% endif %} {% endfor %} ]'> </div> <script type="text/javascript" src="{% static 'base/scripts/maps.js' %}"></script>
修改maps.js代码
从DOM元素读取数据并生成locations数组:
(function($){ "use strict"; function mainMap() { var ib = new InfoBox(); // Infobox Output function locationData(locationURL,locationImg,locationTitle, locationAddress, locationRating, locationRatingCounter) { return('SOME_HTML_WITH_VARIABLES') } // 从DOM读取数据 var mapDataEl = document.getElementById('map-data'); var rawLocations = JSON.parse(mapDataEl.getAttribute('data-locations')); // 转换为符合要求的locations格式 var locations = rawLocations.map(function(item) { return [ locationData('link_to', 'img_url', item[0], item[1], '5', '10'), item[2], item[3], item[4], item[5] ]; }); // 如果没有数据则用默认值 if (!locations.length) { locations = [ [ locationData('listings-single-page.html','images/listing-item-01.jpg',"Tom's Restaurant",'964 School Street, New York', '3.5', '12'), 40.94401669296697, -74.16938781738281, 1, '<i class="im im-icon-Chef-Hat"></i>'], ]; } // ... 后续地图初始化逻辑 ... } mainMap(); })(jQuery);
方案3:封装地图初始化函数,通过参数接收数据
把maps.js的逻辑改成可调用的初始化函数,直接传入数据,这是最符合模块化的方案:
修改maps.js代码
暴露一个全局初始化函数,接收locationsData参数:
(function($){ "use strict"; // 暴露全局初始化函数 window.initMainMap = function(locationsData) { function mainMap() { var ib = new InfoBox(); // Infobox Output function locationData(locationURL,locationImg,locationTitle, locationAddress, locationRating, locationRatingCounter) { return('SOME_HTML_WITH_VARIABLES') } // 使用传入的数据,没有则用默认值 var locations = locationsData || [ [ locationData('listings-single-page.html','images/listing-item-01.jpg',"Tom's Restaurant",'964 School Street, New York', '3.5', '12'), 40.94401669296697, -74.16938781738281, 1, '<i class="im im-icon-Chef-Hat"></i>'], ]; // ... 后续地图初始化逻辑 ... } mainMap(); }; })(jQuery);
模板代码(template.html)
<script type="text/javascript" src="{% static 'base/scripts/maps.js' %}"></script> <!-- 渲染数据并调用初始化函数 --> <script> var mapLocations = [ {% for model in query_list %} [ locationData( 'link_to', 'img_url', '{{ model.name|escapejs }}', '{{ model.address|escapejs }}', '5', '10' ), {{ model.latitude }}, {{ model.longitude }}, {{ forloop.counter }}, '{{ model.icon|escapejs }}' ]{% if not forloop.last %},{% endif %} {% endfor %} ]; // 调用初始化函数并传入数据 window.initMainMap(mapLocations); </script>
关键注意事项
- 一定要使用
|escapejs过滤器处理Django模型中的字符串字段,避免引号、换行符等破坏JS语法,同时防止XSS攻击。 - 如果
locationData的参数(比如link_to、img_url)也需要从Django模型获取,直接替换模板中的硬编码值即可。
内容的提问来源于stack exchange,提问作者GRS
相关产品推荐
相关产品推荐

