1. ホーム
  2. ジャンゴ

[解決済み】Djangoのフォームセットにフォームを動的に追加する

2022-04-03 06:08:19

質問

ユーザが "add" ボタンをクリックすると、新しいフォーム (フォームセットの一部) をページに追加する JavaScript が実行されるように、Django フォームセットに新しいフォームを動的に追加したいのですが、どうすればいいですか?

どのように解決するのですか?

これは、私が行っている方法です。 jQuery :

私のテンプレートです。

<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>

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_' + 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);
}

何をするのか

cloneMore 受け入れる selector を第1引数として指定し type のフォームセットを2つ目として使用します。この 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 を次のように置き換えます。 id_clients-(N)-name から id_clients-(N+1)-name といった具合です。それが終わると TOTAL_FORMS フィールドに新しいフォームを反映させ、セットの末尾に追加します。

この関数は、フォームセットでより多くのフォームを提供したいときにアプリ全体で使用できるように設定されており、フォームセット名とフォームがレイアウトされる形式を渡しさえすれば、複製するための隠しフォーム "テンプレート"を持つ必要がないため、特に役に立っています。お役に立てれば幸いです。