DjangoのFormPreviewを使って確認ページを表示する

なにかのデータを登録する機能で、登録完了する前に確認ページを表示したい、って要件はよくあります。

DjangoではFormPreviewというクラスが用意されているので使ってみます。


まず登録するモデルを作成

from django.db import models
from django_localflavor_jp.jp_prefectures import JP_PREFECTURES


class Address(models.Model):
    name = models.CharField(max_length=100)
    prefecture = models.CharField(max_length=100, choices=JP_PREFECTURES)
    address = models.CharField(max_length=100)

次にformを作成

from django.contrib.formtools.preview import FormPreview
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from apps.models import Address


class AddressForm(forms.ModelForm):
    class Meta:
        model = Address

        widgets = {
            'prefecture': JPPrefectureSelect()
        }

そしてdjango.contrib.formtools.preview.FormPreviewのサブクラスを作成します。
done関数を実装する必要があります。
done関数では、データの登録と、完了ページへのリダイレクトをします。

class AddressFormPreview(FormPreview):

    def done(self, request, cleaned_data):
        address = Address(**cleaned_data)
        address.save()
        return redirect(reverse('address_created', args=(), kwargs={}))

テンプレートを用意します。FormPreviewでは以下のテンプレートを使うようになってます。

class FormPreview(object):
    preview_template = 'formtools/preview.html'
    form_template = 'formtools/form.html'

form.htmlが登録フォームを表示するhtml、preview.htmlが確認ページのhtmlですね。

オーバーライドすれば違うテンプレートが使えますが、用意されてるpreview.htmlとform.htmlを参考にすればいいと思います。

とりあえずコピーしてそのまま使います。あと完了ページ用のhtmlも用意しておきます。
formtools/done.htmlって名前で作成しました

最後にurls.py。FormPreviewと完了ページを定義します。

urlpatterns = patterns('',
    url(r'^/?$', AddressFormPreview(AddressForm)),
    url(r'^address_created/?$', TemplateView.as_view(template_name='formtools/done.html'), name='address_created')
)


これで準備完了。動かしてみます。


登録フォーム



確認ページ


登録完了ページは、用意したdone.htmlが表示されます。
ちゃんと動きました。


確認ページでは入力値はhidden fieldとして保持されてます。
見るとSecurity hashというのが表示されてます。

これをformから飛ばさないと、登録が実行されず、また、hiddenフィールドを書き換えたりして、hash値が一致しなくても登録が実行されません。


一応そんなセキュリティ機能もついてるってわけですね。