你会如何在Django中创建一个动态的formset?
这里是我做的方式:你会如何在Django中创建一个动态的formset?
{{ formset.management_form }}
<table>
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</table>
<a href="javascript:void(0)" id="add_form">Add Form</a>
而这里的JS:
var form_count = {{formset.total_form_count}};
$('#add_form').click(function() {
form_count++;
var form = '{{formset.empty_form|escapejs}}'.replace(/__prefix__/g, form_count);
$('#forms').append(form)
$('#id_form-TOTAL_FORMS').val(form_count);
});
具体什么困扰我的是,我不得不写escapejs
模板标签自己。它只是去除所有换行符,并且转义任何单引号,这样它就不会弄乱我的字符串。但是,在这种情况下,Django制造商究竟希望我们做什么?为什么他们有这个隐藏字段,他们可能刚刚使用了一个像<input name="my_form_field[0]" />
这样的数组,然后计算它的长度呢?
在Django中有一些地方“为什么”是因为它是如何在Django管理应用程序中实现的,我相信这就是其中之一。因此,答案是他们期望你实现你自己的JavaScript。
查看此SO问题Dynamically adding a form...了解更多javascript的想法。
还有两个可插拔的应用程序可用,django-dynamic-formset和django-dinamyc-form,直到现在才查看第一个。
编写我自己的JS并不是一个真正的问题......我只是好奇他们为什么只给我们一半的工具,我们需要......他们说'empty_form'可以是用于这个,但它打印线断行和这样的东西不是很友好的时候尝试填充到JS,除非我误解了一些东西。我认为我更喜欢我的动态formset方法...我怀疑它会减少客户端的压力,并且需要更少的代码:)噢,好吧......我想我只是挑剔,但我仍然真的很不赞同Django的设计决策。 – mpen 2010-03-02 02:39:47
好的,Django恰当的设计决策是保持JS框架中立。管理员是一个contrib应用程序,所以在技术上不是Django核心的一部分,虽然一些功能,如formset(显然)来自于管理员的工作,而我认为管理员是一个很好的应用程序,它可能会受到一定程度的影响从缺乏宏伟的设计。 – 2010-03-02 07:58:26
如果你想用ajax做任何事情或动态添加新对象,Formset是一个巨大的痛苦。 Django尝试设计Web 2.0类型应用程序时,迄今为止最大的问题。出于这个原因,我们在Django投资了6个月后,几乎改用了Java框架,但决定花费太多时间。 – 2011-11-02 06:19:28
这个问题有点旧了,但我花了一段时间才弄清楚了。
我建议将模板中的formset.empty_form呈现为隐藏字段,并在JavaScript中引用此字段。
下面是来自Django管理站点一个复杂的动态表单集例如: (但要注意,它并没有被更新为使用empty_form ....)
[JS] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js
这是因为formset已创建工作没有JavaScript,只使用通常的HTTP工作流程。
Django是javascript不可知论者。
如果你想添加一些javascript的混合,你可以使用dedicated jquery plugin。
希望我能看到演示,但谢谢。 Django的设计目的是在没有JavaScript的情况下工作,是的,但它似乎有一些小的钩子来构建JavaScript ....我只是希望他们更进一步,因为这很痛苦。 – mpen 2012-01-04 22:37:53
@Mark:实际上有一个演示:-)在http://code.google.com/p/django-dynamic-formset/下载该项目,它包含一个django演示。 – 2012-01-05 09:27:41
这不是我演示的意思。我的意思是不必下载它(“现场演示”?)。有数百万个项目和程序在那里......人们喜欢在投入时间和精力,下载和提取内容,和/或安装/编译之前知道他们得到了什么。无论如何,既然你*推荐了它,它不仅仅是我偶然发现的一些随机事物,我会检查出来......(如果它是如此美妙的图书馆,你会期望它会在某个地方使用可以链接到...) – mpen 2012-01-05 16:32:29
在我的情况。我使用了插件django-dynamic-formset(https://code.google.com/p/django-dynamic-formset/wiki/Usage)
并修改了选项“added”并且运行良好。
$('#formset-table tbody tr').formset({ prefix: '{{ formset.prefix }}', formCssClass: '{{ formset.prefix }}-inlineformset', added: function(obj_tr){
var form = $(obj_tr).html().replace(/\-(\w+)\-(\w+)(fix__)\-/g, '-');
$(obj_tr).html(form);
},
这个正则表达式替换字符串[前缀] - 前缀同行 ' - '
也许不是最好的解决办法,但工作。
当使用formset.empty_form
作为字符串时,有一些可能的XSS的情况,将'__prefix__'
替换为实际的formset表单索引。我的可插入应用程序将formset.empty_form
转换为Knockout.js模板,然后通过自定义Knockout.js绑定进行克隆。此外,Knockout.js会自动重新计算表单字段标识索引,当在添加inlineformsets的整个表单提交之前动态删除新添加的表单集表单表单时。下面是文档:加载与内嵌的JavaScript自定义字段时
Knockout.js还结合防止XSS。
但是,你为什么要混合django模板和JavaScript? – Prashanth 2010-03-01 04:38:37
以便我可以处理它。否则,我必须在视图中完全自定义表单处理。 Django似乎鼓励这种方法,那就是*为什么*他们提供了这个'empty_form'和'__prefix__',以便你可以替换它。 – mpen 2010-03-01 06:36:02
我喜欢'.empty_form'的用法 - 很好,很短。谢谢! – 2011-05-24 01:09:26