読者です 読者をやめる 読者になる 読者になる

ModelFormを使ってみた

Django

「普通の」Django開発の原稿を書かなくてはいけないので、ようやくModelFormに触ってみた。
ちょっとトリビアルなモデルだけれども、モデルItemに対するフォームItemFormを定義してみる。

import django.newforms as forms
from django.db import models

class Item(models.Model):
    name = models.CharField(max_length=100)

class ItemForm(forms.ModelForm):
    class Meta:
        model = Item

ビューから使う時には、新規作成ならば、

from django.shortcuts import *
from django.template import RequestContext
from models import Item, ItemForm

def create_item(req):
    form = ItemForm(req.POST or None)
    if form.is_valid():
        new_item = form.save()
        return render_to_response('done.html',
                                  {'item': new_item})

    return render_to_response('form.html',
                              {'form': form})


既存のレコードを変更するならば、

def update_item(req, item_id):
    item = get_object_or_404(Item, id=item_id)
    form = ItemForm(req.POST or None, instance=item)
    if form.is_valid():
        updated_item = form.save()
        return render_to_response('done.html',
                                  {'item': updated_item})

    return render_to_response('form.html',
                              {'form': form})


instance引数にはNoneも渡せるので、上のコードもひとつにまとめることができると思う。

def create_or_update_item(req, item_id=None):
    if item_id is None:
        item = None
    else:
        item = get_object_or_404(Item, id=item_id)

    form = ItemForm(req.POST or None, instance=item)
    if form.is_valid():
        new_item = form.save()
        return render_to_response('done.html',
                                  {'item': new_item})

    return render_to_response('form.html',
                              {'form': form})

ただこのやり方だと、新規作成時と更新時のテンプレートを変えたり、ビュー内での前処理、後処理とかが必要になってくると、あとで困ることになるので、おすすめはしない。


ModelFormサブクラスで明示的にフィールドを指定すると標準のフィールドを置き換えられる。これまたトリビアルな例だけど、inputの代わりにtextareaで出力するならば、次のようにする。

class ItemForm(forms.ModelForm):
    name = forms.CharField(widget=forms.Textarea)

    class Meta:
        model = Item

form_for_model, form_for_instanceの時には、これと同じことをやるのがちょっときれいじゃないなと感じていて、結局真剣に使ったことがなかった。ModelFormはかなりきれいに書ける(Djangoの他のインターフェイスと統一感がある)ので、標準的なDjangoのやり方でモデルやフォームを扱うのもよいかなと思い始めた。