提问人:Dav-C 提问时间:3/20/2021 更新时间:3/22/2021 访问量:222
如何在 django 模板中为 loop 创建唯一的 javascript 变量名?
How can I create unique javascript variable names in a django template for loop?
问:
我正在使用 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>
答:
与其创建多个脚本,不如只使用一个脚本,该脚本适用于所有形式。所以,你可以在 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>
@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);
});
评论
{% for
{{ forloop.counter }}