気ままなタンス*プログラミングなどのノートブック

プログラミングやRPGツクール、DTM、VOCALOIDについてのんびり書きます。

【Django】Formやformsetに初期値を与える(データ更新時等)

データ修正画面で、既存データ修正する際のお話。

ModelFormを継承して利用していれば、HogeForm(instance=hoge)で値を格納してくれるが、
Formの場合はそういうわけにはいかない。

値を格納したい場合は、Formインスタンス作成時に、initialを指定する

initialの指定

# Form
form = AnyForm(initial=dict_obj)

# formsets(formsets.formset_factory)
formset = AnyFormSet(initial=[{'name':'value', 'any_value':'value'},... ])

もう少し詳しいコード

"""any/forms.py"""
from django import forms

# 今回使うForm
class AnyForm(forms.Form):
    name = forms.CharField(max_length=40)
    any_value = forms.CharField(max_length=100)


# Formの明細
class AnyDetailForm(forms.Form):
    detail_value = forms.CharField(max_length=20)


# 今回使うFormSet(Formの明細)
AnyDetailFormSet = forms.formsets.formset_factory(AnyDetailForm, extra=3, max_num=3)


"""any/models.py"""
class AnyModel(models.Model):
    name = models.CharField(max_length=40)
    any_value = forms.CharField(max_length=100)


class AnyDetailModel(models.Model):
    any = models.ForeignKey(AnyModel)
    detail_value = models.CharField(max_length=20)


"""any/views.py"""
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from any.forms import *
from any.models import AnyModel

def edit_any(request, any_id=None):
    if any_id is not None:
        any = get_object_or_404(AnyModel, pk=any_id)
    else:
        any = AnyModel()

    if request.method == "POST":
        pass
    else:
        if any_id:
            # anyの値を辞書に格納し、formを作成:initialを指定
            any_dict = dict(name=any.name, any_value=any.value)
            form = AnyForm(initial=any_dict)

            # any_detailの値を辞書のリストに格納し、formsetsを作成:initialを指定
            detail_list = []
            for any_detail in any.anydetail_set.all():
                detail_dict =  dict(detail_value=any_detail.detail_value)
                detail_list.append(detail_dict)

            form_detail = AnyDetailFormSet(initial=detail_list, prefix=ad)

         else:
            form = AnyForm()
            form_detail = AnyDetailFormSet(prefix=ad)

    return render_to_response('any/edit.html',
                              dict(form=form, form_detail=form_detail, any_id=any_id),
                              RequestContext(request)
                              )

感想

・Formsetsへの値の設定について、見当がつかず、1時間程度考えてしまった
Djangoのドキュメントに書いていたことであり、自身の読み方に疑問を感じた。改善の余地あり

・辞書オブジェクトを指定すれば良いことが理解できた
・ついでに、親モデルのインスタンスから関連する子をたどる、
 「_set」についても復習できて良かった(こいつは、子のquerysetを返してくれる)