将表单动态添加到 Django 表单集 [英] Dynamically adding a form to a Django formset

查看:36
本文介绍了将表单动态添加到 Django 表单集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想动态地将新表单添加到 Django 表单集中,以便当用户单击添加"时按钮,它运行 JavaScript,向页面添加一个新表单(它是表单集的一部分).

解决方案

我就是这样做的,使用 jQuery:

我的模板:

我的服务

{{ serviceFormset.management_form }}{% for form in serviceFormset.forms %}

<table class='no_error'>{{ form.as_table }}

{% 结束为 %}<input type="button" value="Add More" id="add_more"><脚本>$('#add_more').click(function() {cloneMore('div.table:last', 'service');});

在 javascript 文件中:

function cloneMore(selector, type) {var newElement = $(selector).clone(true);var total = $('#id_' + type + '-TOTAL_FORMS').val();newElement.find(':input').each(function() {var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');var id = 'id_' + 名称;$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');});newElement.find('label').each(function() {var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');$(this).attr('for', newFor);});总计++;$('#id_' + type + '-TOTAL_FORMS').val(total);$(选择器).after(newElement);}

它的作用:

cloneMore 接受 selector 作为第一个参数,将 formset 的 type 作为第二个参数.selector 应该做的是传递它应该复制的内容.在本例中,我将它传递给 div.table:last,以便 jQuery 查找具有 table 类的最后一个表.:last 部分很重要,因为 selector 还用于确定新表单将插入的内容.您很可能希望在其余表格的末尾使用它.type 参数使我们可以更新 management_form 字段,特别是 TOTAL_FORMS,以及实际的表单字段.如果您有一个充满 Client 模型的表单集,则管理字段的 ID 将是 id_clients-TOTAL_FORMSid_clients-INITIAL_FORMS,而表单字段的格式为 id_clients-N-fieldnameN 是表单编号,从 0 开始.因此,使用 type 参数,cloneMore 函数会查看当前有多少表单,并遍历新表单中的每个输入和标签,替换来自类似于 id_clients-(N)-nameid_clients-(N+1)-name 等等.完成后,它更新 TOTAL_FORMS 字段以反映新表单并将其添加到集合的末尾.

这个功能对我特别有帮助,因为它的设置方式允许我在整个应用程序中使用它,当我想在一个表单集中提供更多表单时,并且不会让我需要一个隐藏的模板"只要我将表单集名称和表单布局格式传递给它,就可以复制表单.希望有帮助.

I want to dynamically add new forms to a Django formset, so that when the user clicks an "add" button it runs JavaScript that adds a new form (which is part of the formset) to the page.

解决方案

This is how I do it, using jQuery:

My template:

<h3>My Services</h3>
{{ serviceFormset.management_form }}
{% for form in serviceFormset.forms %}
    <div class='table'>
    <table class='no_error'>
        {{ form.as_table }}
    </table>
    </div>
{% endfor %}
<input type="button" value="Add More" id="add_more">
<script>
    $('#add_more').click(function() {
        cloneMore('div.table:last', 'service');
    });
</script>

In a javascript file:

function cloneMore(selector, type) {
    var newElement = $(selector).clone(true);
    var total = $('#id_' + type + '-TOTAL_FORMS').val();
    newElement.find(':input').each(function() {
        var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
        var id = 'id_' + name;
        $(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
    });
    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);
}

What it does:

cloneMore accepts selector as the first argument, and the type of formset as the 2nd one. What the selector should do is pass it what it should duplicate. In this case, I pass it div.table:last so that jQuery looks for the last table with a class of table. The :last part of it is important because the selector is also used to determine what the new form will be inserted after. More than likely you'd want it at the end of the rest of the forms. The type argument is so that we can update the management_form field, notably TOTAL_FORMS, as well as the actual form fields. If you have a formset full of, say, Client models, the management fields will have IDs of id_clients-TOTAL_FORMS and id_clients-INITIAL_FORMS, while the form fields will be in a format of id_clients-N-fieldname with N being the form number, starting with 0. So with the type argument the cloneMore function looks at how many forms there currently are, and goes through every input and label inside the new form replacing all the field names/ids from something like id_clients-(N)-name to id_clients-(N+1)-name and so on. After it is finished, it updates the TOTAL_FORMS field to reflect the new form and adds it to the end of the set.

This function is particularly helpful to me because the way it is setup it allows me to use it throughout the app when I want to provide more forms in a formset, and doesn't make me need to have a hidden "template" form to duplicate as long as I pass it the formset name and the format in which the forms are laid out. Hope it helps.

这篇关于将表单动态添加到 Django 表单集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆