{% 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();
};
};
}
4
一种选择是创建一个包含所有可能形式的formset,但最初将不需要的表单设置为隐藏 - 即 display: none; . 当's necessary to display a form, set it' sss显示到 block 或任何合适的时候 .
15 回答
@Paolo Bergantino
克隆所有附加的处理程序只需修改该行
对于
防止this problem.
查看动态django表单的以下解决方案:
http://code.google.com/p/django-dynamic-formset/
https://github.com/javisantana/django-dinamyc-form/tree/master/frm
他们都使用jQuery并且是特定于django的 . 第一个似乎更精致,并提供了一个非常好的演示下载 .
我认为这是一个更好的解决方案 .
How would you make a dynamic formset in Django?
克隆的东西不是:
当没有初始表格时添加表格
更好地处理表单中的javascript,例如django-ckeditor
保留初始数据
因为上面的所有答案都使用jQuery并使一些事情变得有点复杂,我写了下面的脚本:
首先,您应该将auto_id设置为false,因此禁用重复的id和name . 因为输入名称必须在表单中是唯一的,所有标识都是使用它们完成的,而不是使用id . 您还必须替换
form
,type
和formset的容器 . (在上面的例子中choices
)另一个cloneMore版本,允许对字段进行选择性清理 . 当您需要防止删除多个字段时使用它 .
cloneMore函数存在一个小问题 . 由于它还清除了django自动生成的隐藏字段的值,因此如果您尝试使用多个空表单保存表单集,则会导致django抱怨 .
这是一个修复:
模拟和模仿:
创建一个与 before 单击"add"按钮的情况对应的formset .
加载页面,查看源并记下所有
<input>
字段 .修改formset以对应 after 单击"add"按钮的情况(更改额外字段的数量) .
加载页面,查看源并记下
<input>
字段的更改方式 .创建一些JavaScript,以适当的方式修改DOM,将其从 before 状态移动到 after 状态 .
将该JavaScript附加到"add"按钮 .
虽然我知道formsets使用特殊隐藏的
<input>
字段并且大致知道脚本必须做什么,但我不记得我头脑中的细节 . 我上面描述的是我在你的情况下会做的 .是的,如果您的条目数量有限,我还建议您只在html中渲染它们 . (如果你不这样做,你将不得不使用另一种方法) .
你可以像这样隐藏它们:
然后js非常简单:
一种选择是创建一个包含所有可能形式的formset,但最初将不需要的表单设置为隐藏 - 即
display: none;
. 当's necessary to display a form, set it' sss显示到block
或任何合适的时候 .如果不了解你的“Ajax”正在做什么的更多细节,很难给出更详细的回复 .
Paolo的建议很好地解决了一个问题 - 浏览器的后退/前进按钮 .
如果用户使用后退/前进按钮返回到formset,则不会呈现使用Paolo脚本创建的动态元素 . 对某些人来说可能是一个交易破坏者的问题 .
例:
1)用户使用“添加更多”按钮向表单集添加两个新表单
2)用户填充表单并提交表单集
3)用户单击浏览器中的后退按钮
4)Formset现在缩减为原始形式,所有动态添加的形式都不存在
这根本不是Paolo脚本的缺陷;但dom操作和浏览器缓存是生活中的事实 .
我想可以在会话中存储表单的值,并且当formset加载以再次创建元素并从会话重新加载值时,可以使用一些ajax魔法;但取决于你想要关于同一个用户和表单的多个实例的肛门,这可能会变得非常复杂 .
任何人都有一个很好的建议来处理这个?
谢谢!
有一个jquery plugin for this,我在Django 1.3中设置了inline_form,它运行得很好,包括预填充,客户端表单添加,删除和多个inline_formsets .
我是这样做的,使用jQuery:
我的模板:
在javascript文件中:
它能做什么:
cloneMore
接受selector
作为第一个参数,并将formset的type
作为第二个参数 .selector
应该做的是将它应该复制的内容传递给它 . 在这种情况下,我传递它div.table:last
,以便jQuery查找具有table
类的最后一个表 . 它的:last
部分很重要,因为selector
也用于确定将在之后插入新表单的内容 . 很可能你会在其他表格结束时想要它 .type
参数是这样我们可以更新management_form
字段,特别是TOTAL_FORMS
,以及实际的表单字段 . 如果您的表单集中包含Client
模型,则管理字段的ID为id_clients-TOTAL_FORMS
和id_clients-INITIAL_FORMS
,而表单字段的格式为id_clients-N-fieldname
,其中N
为表单编号,以0
开头 . 因此,使用type
参数,cloneMore
函数会查看当前有多少个表单,并遍历新表单中的每个输入和标签,将所有字段名称/ ID替换为id_clients-(N)-name
到id_clients-(N+1)-name
等等 . 完成后,它会更新TOTAL_FORMS
字段以反映新表单并将其添加到集合的末尾 .这个函数对我特别有用,因为它的设置方式允许我在整个应用程序中使用它,当我想在一个formset中提供更多的表单时,并不需要我有一个隐藏的“模板”表单来复制只要我传递formset名称和表单的格式 . 希望能帮助到你 .
我从一个我曾经工作的应用程序posted a snippet . 与Paolo相似,但也允许您删除表单 .
对于那些正在寻找资源以便更好地了解上述解决方案的编码人员:
Django Dynamic Formsets
阅读上面的链接后,Django文档和以前的解决方案应该更有意义 .
Django Formset Documentation
作为我对此感到困惑的快速摘要:管理表格包含对其中表单的概述 . 您必须保持该信息的准确性,以便Django了解您添加的表单 . (社区,如果我的一些措辞不在这里,请给我建议 . 我是Django的新手 . )
使用empty_form作为模板的Paolo答案的简化版本 .