如何在 django 模板中为循环创建唯一的 javascript 变量名?
Posted
技术标签:
【中文标题】如何在 django 模板中为循环创建唯一的 javascript 变量名?【英文标题】:How can I create unique javascript variable names in a django template for loop? 【发布时间】:2021-06-17 09:33:13 【问题描述】:我正在使用 django 模板循环访问 hp_tracker 对象。每个 hp_tracker 都有自己的 js 代码,用于通过 ajax 更改值。我几乎可以肯定我应该在 .js 文件中包含此代码,但是我很难找到一种方法来唯一地选择每个 hp_tracker 而无需访问 .js 文件中的 django 模板变量。所以...我将 js 移到了 html 模板本身。我知道这无疑会产生巨大的安全隐患,我也愿意讨论这些问题。
不管怎样,我的问题。我的 js 失败了,因为我声明了不唯一的全局变量(!)。它们被用来控制一些计数器和 setTimeout,我不知道现在如何使用它们来做我想做的事情。
所以 for 循环试图一遍又一遍地重新声明同一个变量。在脚本的其余部分中,我使用的是 JQuery,它非常乐意使用 django 变量 hp_tracker.id ,但 javascript 不是因为变量名称中不允许使用对象 ID 中的“-”字符.
我到底应该怎么做才能解决这个热点问题。有没有办法在没有全局变量的情况下运行我的代码?我可以在不使用对象 ID 的情况下识别我的 for 循环中的对象吗?
<div id="ToolSessionPageWrapper">
<div class="tool-session-page-header">
<div id=OpenToolSelectionMenuBtn class="arrow-down"></div>
</div>
<div class="tool-session-page-body">
<div id="HpTrackersViewWrapper" class="tool-body">
% for hp_tracker in hp_trackers %
<div class="hp-tracker-box">
<div id="hp_tracker.id-HpTrackerTitle" class="hp-tracker-title"> hp_tracker.title </div>
<br />
<form method="POST" action="% url 'hp_change_value' hp_tracker.id %" id=" hp_tracker.id -HpValueForm">
% csrf_token %
<div class="hp-control-box">
<button type="button" id=" hp_tracker.id -HpValueDecreaseBtn" class="hp-value-change-btn decrease">-</button>
<div id="hp_tracker.id-HpValue" class="hp-value"> hp_tracker.hp_value </div>
<div id=" hp_tracker.id -HpValueInput"> hp_change_value_form.hp_value </div>
<div id=" hp_tracker.id -HpChangeValueCover" class="hp-value hp-change-value-cover"></div>
<div id=" hp_tracker.id -HpChangeValue" class="hp-value hp-change-value"></div>
<button type="button" id=" hp_tracker.id -HpValueIncreaseBtn" class="hp-value-change-btn increase">+</button>
</div>
</form>
</div>
<script>
#ajax call for HpValueForm#
function changeHpValue(form)
'use strict';
$(form).submit(function (e)
// preventing from page reload and default actions
e.preventDefault();
// serialize the form data.
let serializedData = $(form).serialize();
// make POST ajax call
$.ajax(
type: 'POST',
url: '% url 'hp_change_value' hp_tracker.id %',
data: serializedData,
success: function (response)
let form_instance = JSON.parse(response['form_instance']);
let fields = form_instance[0]['fields'];
$('#hp_tracker.id-HpValue').empty().prepend(fields.hp_value);
console.log('ajaxSuccess');
,
error: function (response)
console.log(response["responseJSON"]["error"]);
);
);
#control timeout before hp_value increase or decrease is submitted#
let hp_tracker.id|escapejs hp_add_subtract_value = $('#hp_tracker.id-HpValue').text(),
hp_change_value = 0,
timeoutHandler;
function timeoutControl()
clearTimeout(timeoutHandler);
timeoutHandler = setTimeout(function ()
$('# hp_tracker.id -HpValueInput input').val(hp_add_subtract_value);
$('# hp_tracker.id -HpValueForm').submit();
$('#hp_tracker.id-HpChangeValue').css('display': 'none');
$('#hp_tracker.id-HpChangeValueCover').css('display': 'none');
hp_change_value = 0;
$('#hp_tracker.id-HpChangeValue').empty().prepend(hp_change_value);
, 2000);
#increase the hp value#
$('# hp_tracker.id -HpValueIncreaseBtn').click(function (e)
'use strict';
hp_add_subtract_value++;
hp_change_value++;
$('#hp_tracker.id-HpChangeValue').css('display': 'inline');
$('#hp_tracker.id-HpChangeValueCover').css('display': 'inline');
$('#hp_tracker.id-HpChangeValue').empty().prepend(hp_change_value);
timeoutControl();
);
#decrease the hp value#
$('# hp_tracker.id -HpValueDecreaseBtn').click(function (e)
'use strict';
hp_add_subtract_value--;
hp_change_value--;
$('#hp_tracker.id-HpChangeValue').css('display': 'inline');
$('#hp_tracker.id-HpChangeValueCover').css('display': 'inline');
$('#hp_tracker.id-HpChangeValue').empty().prepend(hp_change_value);
timeoutControl();
);
#submit HpValueForm#
$('# hp_tracker.id -HpValueForm').on('submit', changeHpValue('# hp_tracker.id -HpValueForm'));
</script>
% endfor %
</div>
</div>
【问题讨论】:
查看% for
上的文档。您可以执行 forloop.counter
之类的操作来获取当前循环索引。这应该可以帮助您创建唯一的名称 - docs.djangoproject.com/en/3.1/ref/templates/builtins/#for
啊,是的,我没想到。我去看看!
你好,有必要把django代码放在jquery里面吗?
我在 jQuery 中使用 Django 变量作为选择器来识别由 Django 模板系统动态生成的元素。不过,我对所有想法都持开放态度!
【参考方案1】:
您可以只创建一个适用于所有形式的脚本,而不是创建多个脚本。因此,您可以在 django 代码中进行更改:
<div id="HpTrackersViewWrapper" class="tool-body">
% for hp_tracker in hp_trackers %
<div class="hp-tracker-box">
<div id="hp_tracker.id-HpTrackerTitle" class="hp-tracker-title"> hp_tracker.title </div>
<br />
//add data-id ... and a class
<form method="POST" action="% url 'hp_change_value' hp_tracker.id %" data-id ="hp_tracker.id" class="form_to_submit" id=" hp_tracker.id -HpValueForm">
% csrf_token %
<div class="hp-control-box">
<button type="button" id=" hp_tracker.id -HpValueDecreaseBtn" class="hp-value-change-btn decrease">-</button>
<div id="hp_tracker.id-HpValue" class="hp-value"> hp_tracker.hp_value </div>
<div id=" hp_tracker.id -HpValueInput"> hp_change_value_form.hp_value </div>
<div id=" hp_tracker.id -HpChangeValueCover" class="hp-value hp-change-value-cover"></div>
<div id=" hp_tracker.id -HpChangeValue" class="hp-value hp-change-value"></div>
<button type="button" id=" hp_tracker.id -HpValueIncreaseBtn" class="hp-value-change-btn increase">+</button>
</div>
</form>
</div>
//remove whole script from here
% endfor %
</div>
然后,您的 jquery 代码将如下所示:
//on submit of form
$(".form_to_submit").submit(function(e)
e.preventDefault();
//get ids..
var data_id = $(this).data("id")
let serializedData = $(this).serialize();
console.log(data_id)
// make POST ajax call
$.ajax(
type: 'POST',
url: '% url hp_change_value ' + data_id + ' %', //pass here id
data: serializedData,
success: function(response)
let form_instance = JSON.parse(response['form_instance']);
let fields = form_instance[0]['fields'];
$('#' + data_id + '-HpValue').empty().prepend(fields.hp_value);
console.log('ajaxSuccess');
,
error: function(response)
console.log(response["responseJSON"]["error"]);
);
);
var timeoutHandler;
function timeoutControl(el)
clearTimeout(timeoutHandler);
//get closet form
var selector = $(el).closest("form")
//get hp values
var hp_add_subtract_value = selector.find(".hp-value").text()
//get id
var data_id = selector.data('id')
timeoutHandler = setTimeout(function()
$('#' + data_id + '-HpValueInput input').val(hp_add_subtract_value);
selector.submit();
selector.find('.hp-change-value').css(
'display': 'none'
);
selector.find('.hp-change-value-cover').css(
'display': 'none'
);
hp_change_value = 0;
selector.find('.hp-change-value').empty().prepend(hp_change_value);
, 2000);
$('.increase').click(function(e)
var selector = $(this).closest(".hp-control-box")
var hp_add_subtract_value = parseInt(selector.find(".hp-value").text())
hp_add_subtract_value++;
var hp_change_value = selector.find(".hp-change-value").text().trim() != "" ? parseInt(selector.find(".hp-change-value").text().trim()) : 0
selector.find('.hp-change-value').css(
'display': 'inline'
);
selector.find('.hp-change-value-cover').css(
'display': 'inline'
);
selector.find('.hp-change-value').empty().prepend(hp_change_value);
timeoutControl(this); //here this refer to increase button which is clickde..
);
$('.decrease').click(function(e)
//get closest outer box..
var selector = $(this).closest(".hp-control-box")
//use find to get other values..
var hp_add_subtract_value = parseInt(selector.find(".hp-value").text())
var hp_change_value = selector.find(".hp-change-value").text().trim() != "" ? parseInt(selector.find(".hp-change-value").text().trim()) : 0
hp_add_subtract_value--;
hp_change_value--;
//change doms ,,,
selector.find('.hp-change-value').css(
'display': 'inline'
);
selector.find('.hp-change-value-cover').css(
'display': 'inline'
);
selector.find('.hp-change-value').empty().prepend(hp_change_value);
timeoutControl(this); //refer the button which is clicked
);
演示代码:
//on submit of form
$(".form_to_submit").submit(function(e)
e.preventDefault();
//get ids..
var data_id = $(this).data("id")
let serializedData = $(this).serialize();
console.log(data_id)
// make POST ajax call
/*$.ajax(
type: 'POST',
url: '% url hp_change_value ' + data_id + ' %', //pass here id
data: serializedData,
success: function(response)
let form_instance = JSON.parse(response['form_instance']);
let fields = form_instance[0]['fields'];*/
$('#' + data_id + '-HpValue').empty().prepend(44); //just for demo...
/* console.log('ajaxSuccess');
,
error: function(response)
console.log(response["responseJSON"]["error"]);
);*/
);
var timeoutHandler;
function timeoutControl(el)
clearTimeout(timeoutHandler);
//get closet form
var selector = $(el).closest("form")
//get hp values
var hp_add_subtract_value = selector.find(".hp-value").text()
//get id
var data_id = selector.data('id')
timeoutHandler = setTimeout(function()
$('#' + data_id + '-HpValueInput input').val(hp_add_subtract_value);//don't know where is input in your code..:P
selector.submit();
selector.find('.hp-change-value').css(
'display': 'none'
);
selector.find('.hp-change-value-cover').css(
'display': 'none'
);
hp_change_value = 0;
selector.find('.hp-change-value').empty().prepend(hp_change_value);
, 2000);
$('.increase').click(function(e)
var selector = $(this).closest(".hp-control-box")
var hp_add_subtract_value = parseInt(selector.find(".hp-value").text())
hp_add_subtract_value++;
var hp_change_value = selector.find(".hp-change-value").text().trim() != "" ? parseInt(selector.find(".hp-change-value").text().trim()) : 0
selector.find('.hp-change-value').css(
'display': 'inline'
);
selector.find('.hp-change-value-cover').css(
'display': 'inline'
);
selector.find('.hp-change-value').empty().prepend(hp_change_value);
timeoutControl(this); //here this refer to increase button which is clickde..
);
$('.decrease').click(function(e)
//get closest outer box..
var selector = $(this).closest(".hp-control-box")
//use find to get other values..
var hp_add_subtract_value = parseInt(selector.find(".hp-value").text())
var hp_change_value = selector.find(".hp-change-value").text().trim() != "" ? parseInt(selector.find(".hp-change-value").text().trim()) : 0
hp_add_subtract_value--;
hp_change_value--;
//change doms ,,,
selector.find('.hp-change-value').css(
'display': 'inline'
);
selector.find('.hp-change-value-cover').css(
'display': 'inline'
);
selector.find('.hp-change-value').empty().prepend(hp_change_value);
timeoutControl(this); //refer the button which is clicked
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="hp-tracker-box">
<div id="1-HpTrackerTitle" class="hp-tracker-title">Soemthings ...,,</div>
<br />
<!--here added data-id , class as well-->
<form method="POST" action="% url 'hp_change_value' 1 %" data-id="1" class="form_to_submit" id="1-HpValueForm">
% csrf_token %
<div class="hp-control-box">
<button type="button" id="1-HpValueDecreaseBtn" class="hp-value-change-btn decrease">-</button>
<div id="1-HpValue" class="hp-value">22</div>
<div id="1-HpValueInput">23</div>
<div id="1-HpChangeValueCover" class="hp-value hp-change-value-cover"></div>
<div id="1-HpChangeValue" class="hp-value hp-change-value"></div>
<button type="button" id="1-HpValueIncreaseBtn" class="hp-value-change-btn increase">+</button>
</div>
</form>
</div>
<div class="hp-tracker-box">
<div id="1-HpTrackerTitle" class="hp-tracker-title">Soemthings ...,,</div>
<br />
<form method="POST" action="% url 'hp_change_value' 2 %" data-id="2" class="form_to_submit" id="2-HpValueForm">
% csrf_token %
<div class="hp-control-box">
<button type="button" id="2-HpValueDecreaseBtn" class="hp-value-change-btn decrease">-</button>
<div id="2-HpValue" class="hp-value">22</div>
<div id="2-HpValueInput">23</div>
<div id="2-HpChangeValueCover" class="hp-value hp-change-value-cover"></div>
<div id="2-HpChangeValue" class="hp-value hp-change-value"></div>
<button type="button" id="2-HpValueIncreaseBtn" class="hp-value-change-btn increase">+</button>
</div>
</form>
</div>
【讨论】:
【参考方案2】:@Swati,您的回答并没有完全满足我的需要,但您确实将我推向了正确的方向,并帮助我填补了我对这一切如何运作的理解中的一些漏洞。所以我把你的答案标记为正确,谢谢你的帮助!这是我最终使用的代码(我知道 ajax 错误函数不起作用,但那是另一天......):
html
<div id="ToolSessionPageWrapper">
<div class="tool-session-page-header">
<div id=OpenToolSelectionMenuBtn class="arrow-down"></div>
</div>
<div class="tool-session-page-body">
<div id="HpTrackersViewWrapper" class="tool-body">
% for hp_tracker in hp_trackers %
<div class="hp-tracker-box">
<div id="hp_tracker.id-HpTrackerTitle" class="hp-tracker-title"> hp_tracker.title </div>
<br />
<form method="POST" action="% url 'hp_change_value' hp_tracker.id %" id=" hp_tracker.id -HpValueForm" data-id=" hp_tracker.id " class="hp-value-change-form">
% csrf_token %
<div class="hp-control-box">
<button type="button" data-id=" hp_tracker.id -HpValueDecreaseBtn" class="hp-value-change-btn decrease">-</button>
<div id=" hp_tracker.id -HpValue" class="hp-value"> hp_tracker.hp_value </div>
<div id=" hp_tracker.id -HpValueInput"> hp_change_value_form.hp_value </div>
<div id=" hp_tracker.id -HpValueChangeCover" class="hp-value hp-change-value-cover"></div>
<div id=" hp_tracker.id -HpValueChange" class="hp-value hp-change-value"></div>
<button type="button" data-id=" hp_tracker.id -HpValueIncreaseBtn" class="hp-value-change-btn increase">+</button>
</div>
</form>
</div>
% endfor %
</div>
</div>
js
// ajax call for HpValueForm
$('.hp-value-change-form').submit(function(e)
'use strict';
e.preventDefault();
let data_id = $(this).attr("data-id");
// serialize the form data.
let serializedData = $(this).serialize();
// make POST ajax call
$.ajax(
type: 'POST',
url: $(this).attr('action'),
data: serializedData,
success: function (response)
let form_instance = JSON.parse(response['form_instance']);
let fields = form_instance[0]['fields'];
$("#" + data_id + "-HpValue").empty().prepend(fields.hp_value);
console.log('ajaxSuccess');
,
error: function (response)
console.log(response["responseJSON"]["error"]);
);
);
//control timeout before hp_value increase or decrease is submitted
localStorage.setItem('hp_change_value', '0');
let timeoutHandler;
function timeoutControl(element)
'use strict';
clearTimeout(timeoutHandler);
// select the closest for to the clicked button
let selector = $(element).closest('.hp-value-change-form');
// assign the unique django object id to a variable
let data_id = selector.attr("data-id");
// get the hp change value from local storage
let hp_change_value = parseInt(localStorage.getItem('hp_change_value'));
// get the current hp value being provided by django context
let hp_initial_value = parseInt($("#" + data_id + "-HpValue").text());
// calculate the amount to be entered into the hp value change form
let hp_add_subtract_value = hp_initial_value + hp_change_value;
// After a 2 second delay submit the form and reset the change value to 0
timeoutHandler = setTimeout(function ()
$('#' + data_id + '-HpValueInput input').val(hp_add_subtract_value);
$('#' + data_id + '-HpValueForm').submit();
$('#' + data_id + '-HpValueChange').css('display': 'none');
$('#' + data_id + '-HpValueChangeCover').css('display': 'none');
localStorage.setItem('hp_change_value', '0');
, 2000);
// increase the hp value with each button click - value is not submitted until
// after a 2 second delay via timeoutControl()
$('.hp-value-change-btn.increase').click(function (e)
'use strict';
let selector = $(this).closest('.hp-control-box');
let hp_change_value = parseInt(localStorage.getItem('hp_change_value'));
hp_change_value++;
localStorage.setItem('hp_change_value', hp_change_value.toString());
$(selector.find('.hp-change-value')).css('display': 'inline');
$(selector.find('.hp-change-value-cover')).css('display': 'inline');
$(selector.find('.hp-change-value')).empty().prepend(hp_change_value);
timeoutControl(this);
);
// decrease the hp value with each button click - value is not submitted until
// after a 2 second delay via timeoutControl()
$('.hp-value-change-btn.decrease').click(function (e)
'use strict';
let selector = $(this).closest('.hp-control-box');
let hp_change_value = parseInt(localStorage.getItem('hp_change_value'));
hp_change_value--;
localStorage.setItem('hp_change_value', hp_change_value.toString());
$(selector.find('.hp-change-value')).css('display': 'inline');
$(selector.find('.hp-change-value-cover')).css('display': 'inline');
$(selector.find('.hp-change-value')).empty().prepend(hp_change_value);
timeoutControl(this);
);
【讨论】:
以上是关于如何在 django 模板中为循环创建唯一的 javascript 变量名?的主要内容,如果未能解决你的问题,请参考以下文章
如何为 django 模板中的单个按钮的 for 循环中的按钮提供唯一 id?