jQueryでDjangoのformsetの表示を制御するjquery.formset.jsを試してみた


複数の同じフォームの表示をしたい場合、Djangoではformsetが用意されてます。
https://docs.djangoproject.com/en/1.4/topics/forms/formsets/

普通に使うと、複数のフォームが同時に表示されます。


「最初はフォームをひとつだけ表示し、必要に応じて増減させたい」という場合は、javascriptを使って表示非表示を制御したりしますが、
その部分を担ってくれるライブラリを見つけたので、どんな感じか試してみました。

django-dynamic-formset
http://code.google.com/p/django-dynamic-formset/


まずFormとFormsetを用意します


forms.py

from django.forms.formsets import formset_factory
from django import forms

class TweetForm(forms.Form):
    tweet = forms.CharField(widget=forms.Textarea, max_length=140)

TweetFormSet = formset_factory(TweetForm, extra=1, max_num=100)


表示してみたいだけなので、view関数は簡単なものです


views.py

from django.shortcuts import render_to_response
from forms import TweetFormSet

def index(request):
    formset = TweetFormSet()
    
    return render_to_response('app/index.html',
            {'formset': formset })


テンプレートでformsetを描画します。jqueryjquery.formset.jsを読み込みます

index.html

<!-- 抜粋 -->

    <form id="myForm" action="#">
        {% for form in formset %}
            <div class="each_form">
                {{ form.tweet }}
            </div>
        {% endfor %}
        {{ formset.management_form }}

        <div>
            <input type="submit" value="submit"/>
        </div>
    </form>

<!-- 抜粋 -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="/path/to/jquery.formset.js"></script>


formsetの表示を制御するjs部分はこんな感じ

    $(function() {
        $('#myForm div.each_form').formset({
            prefix: '{{ formset.prefix }}',
        });
    })


オプションは以下を渡せます


jqeury.formset.jsから抜粋

    /* Setup plugin defaults */
    $.fn.formset.defaults = {
        prefix: 'form',                  // The form prefix for your django formset
        addText: 'add another',          // Text for the add link
        deleteText: 'remove',            // Text for the delete link
        addCssClass: 'add-row',          // CSS class applied to the add link
        deleteCssClass: 'delete-row',    // CSS class applied to the delete link
        formCssClass: 'dynamic-form',    // CSS class applied to each form in a formset
        added: null,                     // Function called each time a new form is added
        removed: null                    // Function called each time a form is deleted
    }

簡単に導入できるのがいいですね。
ただ細かい挙動まで要件で指定されそうな場合は、自前で実装しておいたほうがいいような気もします。

最新のバージョンは1.2ですが、追加される入力フォームのidがちょっとおかしかったり、フォームが0個になるまで削除できてしまったりしたので1.1を使いました。

とりあえず動くようになったのでherokuにアップしました
http://formset-sample.herokuapp.com/

githubにもおいた
https://github.com/yuhei0718/jquery-formset-sample