FormPreviewを使って確認ページ有りの更新機能を実装する

昨日さわってみたFormPreviewですが、ぱっと見た感じだと更新機能に対応できないように見えたので、いろいろ調べてみました。

以下はFormPreviewでフォームを表示する部分の関数です。

    def preview_get(self, request):
        "Displays the form"
        f = self.form(auto_id=self.get_auto_id(), initial=self.get_initial(request))
        return render_to_response(self.form_template,
            self.get_context(request, f),
            context_instance=RequestContext(request))


formのインスタンスを作成するときに、initialを指定できるようです。get_initialは空実装になってます

    def get_initial(self, request):
        """
        Takes a request argument and returns a dictionary to pass to the form's
        ``initial`` kwarg when the form is being created from an HTTP get.
        """
        return {}

更新対象のデータを取得するために、idをパラメータで受け取るようにします。

urls.py

    url(r'^update/(?P<id>\d+)/$', AddressUpdatePreview(AddressForm)),


パスに含まれたパラメータはparse_paramsをオーバーライドして取得します。
元々は空実装

    def parse_params(self, *args, **kwargs):
        """
        Given captured args and kwargs from the URLconf, saves something in
        self.state and/or raises Http404 if necessary.

        For example, this URLconf captures a user_id variable:

            (r'^contact/(?P<user_id>\d{1,6})/$', MyFormPreview(MyForm)),

        In this case, the kwargs variable in parse_params would be
        {'user_id': 32} for a request to '/contact/32/'. You can use that
        user_id to make sure it's a valid user and/or save it for later, for
        use in done().
        """
        pass

self.stateに値を突っ込んでおけば、画面遷移を通して値を取得できます。


FormPreviewをオーバーライドしたクラスの全体はこんな感じ

class AddressUpdatePreview(FormPreview):

    def parse_params(self, *args, **kwargs):
        self.state["address_id"] = kwargs["id"]

    def get_initial(self, request):
        address = Address.objects.filter(pk=self.state["address_id"]).values()[0]
        return address

    def done(self, request, cleaned_data):
        address = Address.objects.get(pk=self.state["address_id"])
        for (key, value) in cleaned_data.items():
            setattr(address, key, value)
        address.save()
        return redirect(reverse('address_created', args=(), kwargs={}))


これでFormPreviewを使って更新機能が実装できました。