我想动态地向Django表单集添加新表单,这样当用户点击“添加”按钮时,它就会运行JavaScript,向页面添加新表单(这是表单集的一部分)。
当前回答
另一个cloneMore版本,允许对字段进行选择性消毒。当您需要防止多个字段被擦除时使用它。
$('table tr.add-row a').click(function() {
toSanitize = new Array('id', 'product', 'price', 'type', 'valid_from', 'valid_until');
cloneMore('div.formtable table tr.form-row:last', 'form', toSanitize);
});
function cloneMore(selector, type, sanitize) {
var newElement = $(selector).clone(true);
var total = $('#id_' + type + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
var namePure = $(this).attr('name').replace(type + '-' + (total-1) + '-', '');
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).removeAttr('checked');
if ($.inArray(namePure, sanitize) != -1) {
$(this).val('');
}
});
newElement.find('label').each(function() {
var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
$(this).attr('for', newFor);
});
total++;
$('#id_' + type + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
其他回答
对于那些正在寻找资源以更好地理解上述解决方案的程序员:
Django动态表单
读完上面的链接后,Django文档和以前的解决方案应该更有意义了。
Django Formset文档
作为对我所困惑的内容的快速总结:管理表单包含其中表单的概述。你必须保证这些信息的准确性,这样Django才能知道你添加的表单。(社区,如果我的一些措辞不正确,请给我建议。我刚接触Django。)
是的,如果你有有限数量的条目,我也建议在html中渲染它们。(如果你不这样做,你将不得不使用另一个方法)。
你可以像这样隐藏它们:
{% for form in spokenLanguageFormset %}
<fieldset class="languages-{{forloop.counter0 }} {% if spokenLanguageFormset.initial_forms|length < forloop.counter and forloop.counter != 1 %}hidden-form{% endif %}">
然后js真的很简单:
addItem: function(e){
e.preventDefault();
var maxForms = parseInt($(this).closest("fieldset").find("[name*='MAX_NUM_FORMS']").val(), 10);
var initialForms = parseInt($(this).closest("fieldset").find("[name*='INITIAL_FORMS']").val(), 10);
// check if we can add
if (initialForms < maxForms) {
$(this).closest("fieldset").find("fieldset:hidden").first().show();
if ($(this).closest("fieldset").find("fieldset:visible").length == maxForms ){
// here I'm just hiding my 'add' link
$(this).closest(".control-group").hide();
};
};
}
因为上面所有的答案都使用jQuery,使一些事情有点复杂,我写了下面的脚本:
function $(selector, element) {
if (!element) {
element = document
}
return element.querySelector(selector)
}
function $$(selector, element) {
if (!element) {
element = document
}
return element.querySelectorAll(selector)
}
function hasReachedMaxNum(type, form) {
var total = parseInt(form.elements[type + "-TOTAL_FORMS"].value);
var max = parseInt(form.elements[type + "-MAX_NUM_FORMS"].value);
return total >= max
}
function cloneMore(element, type, form) {
var totalElement = form.elements[type + "-TOTAL_FORMS"];
total = parseInt(totalElement.value);
newElement = element.cloneNode(true);
for (var input of $$("input", newElement)) {
input.name = input.name.replace("-" + (total - 1) + "-", "-" + total + "-");
input.value = null
}
total++;
element.parentNode.insertBefore(newElement, element.nextSibling);
totalElement.value = total;
return newElement
}
var addChoiceButton = $("#add-choice");
addChoiceButton.onclick = function() {
var choices = $("#choices");
var createForm = $("#create");
cloneMore(choices.lastElementChild, "choice_set", createForm);
if (hasReachedMaxNum("choice_set", createForm)) {
this.disabled = true
}
};
首先,您应该将auto_id设置为false,从而禁用id和name的复制。因为输入名称在表单中必须是唯一的,所以所有的标识都是用它们来完成的,而不是用id。 您还必须替换表单集的表单、类型和容器。(在上述选择的例子中)
一种选择是创建一个包含所有可能表单的表单集,但最初将不需要的表单设置为隐藏——即display: none;。当需要显示一个表单时,将它的css显示设置为block或任何合适的显示。
如果不了解更多关于“Ajax”正在做什么的细节,就很难给出更详细的回应。
模拟和模仿:
Create a formset which corresponds to the situation before clicking the "add" button. Load the page, view the source and take a note of all <input> fields. Modify the formset to correspond to the situation after clicking the "add" button (change the number of extra fields). Load the page, view the source and take a note of how the <input> fields changed. Create some JavaScript which modifies the DOM in a suitable way to move it from the before state to the after state. Attach that JavaScript to the "add" button.
虽然我知道表单集使用特殊的隐藏<input>字段,并且大约知道脚本必须做什么,但我不记得我头顶上的细节。我上面所描述的就是我在你的情况下会做的事情。
推荐文章
- django MultiValueDictKeyError错误,我如何处理它
- 我如何在Django中创建一个鼻涕虫?
- 没有名为'django.core.urlresolvers'的模块
- Django - makemigrations -未检测到任何更改
- ">", "<", ">=" 和“< =”不工作”在Django过滤()”
- Django项目工作目录结构的最佳实践
- 如何在Django中表达一对多关系?
- 用Django创建电子邮件模板
- Django的嵌套元类是如何工作的?
- 用Django实现OpenID的最佳解决方案是什么?
- 在使用信号时,你不能在'原子'块的末尾执行查询,但只能在单元测试期间执行
- Django查询- id vs pk
- render(), render_to_response()和direct_to_template()之间有什么区别?
- 如何使用MySQLdb与Python和Django在OSX 10.6?
- 如何在Django中一次添加多个对象到ManyToMany关系?