简体   繁体   English

您将如何在 Django 中制作动态表单集?

[英]How would you make a dynamic formset in Django?

Here's the way I'm doing it:这是我的做法:

{{ formset.management_form }}
<table>
    {% for form in formset.forms %}
        {{ form }}
    {% endfor %}
</table>
<a href="javascript:void(0)" id="add_form">Add Form</a>   

And here's the JS:这是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);
});

What specifically bothers me is that I had to write that escapejs template tag myself.特别困扰我的是我必须自己编写该escapejs模板标签。 It just strips all newlines and escapes any single quotes so that it doesn't mess up my string.它只是去除所有换行符并转义任何单引号,以免弄乱我的字符串。 But what exactly did the Django makers expect us to do in this situation?但是在这种情况下,Django 的制作者究竟希望我们做什么呢? And why do they have this TOTAL_FORMS hidden field, when they could have just used an array like <input name="my_form_field[0]" /> and then counted its length instead?为什么他们有这个TOTAL_FORMS隐藏字段,当他们可以只使用像<input name="my_form_field[0]" />这样的数组然后计算它的长度时呢?

There are a few places in Django where "the reason why" is because that's how it was implemented for the Django admin app, and I believe this is one of them. Django 中有几个地方“原因”是因为这就是为 Django 管理应用程序实现的方式,我相信这是其中之一。 Thus the answer is they expect you to implement your own javascript.因此,答案是他们希望您实现自己的 javascript。

See this SO question Dynamically adding a form... for some more javascript ideas.请参阅此问题动态添加表单...了解更多 javascript 想法。

There are also two pluggable apps available, django-dynamic-formset and django-dinamyc-form which I hadn't seen until just now when looking up the first one.还有两个可插入的应用程序可用, django-dynamic-formsetdjango-dinamyc-form ,我直到刚才在查找第一个时才看到。

This question is a bit old, but it took me a while to figure this out as well.这个问题有点老了,但我也花了一段时间才弄明白。

I suggest rendering formset.empty_form in your template as a hidden field, and referencing this field in your javascript.我建议将模板中的 formset.empty_form 渲染为隐藏字段,并在您的 javascript 中引用此字段。

Here's a complicated dynamic formset example from the django admin site: (but note that it has not been updated to use empty_form....)这是来自 django 管理站点的复杂动态表单集示例:(但请注意,它尚未更新为使用 empty_form....)

[js] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js [js] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js

[html template] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html [html 模板] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html

It's because formset have been created to work without javascript , using only the usual HTTP workflow.这是因为 formset 已被创建为在没有 javascript 的情况下工作,仅使用通常的 HTTP 工作流程。

Django is javascript agnostic. Django 与 JavaScript 无关。

If you want to add some javascript to the mix, you can use the dedicated jquery plugin .如果你想添加一些 javascript,你可以使用专用的 jquery 插件

in my case.就我而言。 i used the plugin django-dynamic-formset ( https://code.google.com/p/django-dynamic-formset/wiki/Usage )我使用了插件 django-dynamic-formset ( https://code.google.com/p/django-dynamic-formset/wiki/Usage )

and modified the option "added" and worked good.并修改了“添加”选项并且效果很好。

 $('#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);

           },

this regular expression replace the string [prefix]- prefix peer '-'此正则表达式替换字符串 [prefix]-前缀peer '-'

maybe isn't the best solution, but worked.也许不是最好的解决方案,但有效。

There are some cases of possible XSS when using formset.empty_form as a string, replacing '__prefix__' to actual formset form index.当使用formset.empty_form作为字符串时,有一些可能的 XSS 情况,将'__prefix__'替换为实际的表单集表单索引。 My pluggable application converts formset.empty_form into Knockout.js template which is then cloned via custom Knockout.js bindings.我的可插入应用程序将formset.empty_form转换为 Knockout.js 模板,然后通过自定义 Knockout.js 绑定克隆该模板。 Also Knockout.js automatically re-calculates form field id indexes, when newly added formset form is dynamically deleted before the whole form with inlineformsets was submitted. Knockout.js 还会自动重新计算表单字段 id 索引,当新添加的表单集表单在提交带有内联表单集的整个表单之前被动态删除时。 Here is the documentation:这是文档:

https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#dynamically-adding-new-related-formset-forms https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#dynamically-adding-new-related-formset-forms

Knockout.js binding also prevents XSS when loading custom fields with inline Javascript.当使用内联 Javascript 加载自定义字段时,Knockout.js 绑定还可以防止 XSS。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM