Django でウィザード形式のページを作りたいとき、SessionWizardView がとても便利ですね。SessionWizardView は、Django 1.7 まで django.contrib.formtools として組み込まれていましたが、Django 1.8 から別リポジトリ管理となりました。(なんででしょう?)
そんな SessionWizardView ですが、基本的な使い方でやるとフォーム数(ステップ数)が固定になります。それをどーしても動的にしたかったのですが、結構苦労したので、共有したいと思います。(何を言ってるのか全然わかりませんね・・・)
Contents
バージョン
- Python 3.6.4
- Django 2.0.3
- django-formtools 2.1
インストール
Django
Django のインストールは、こちら(Python Webフレームワーク Django を始める)を参考にしてください。
django-formtools
Django をインストールしたら、django-formtools をインストールします。
[root@localhost ~]# pip3 install django-formtools Collecting django-formtools Downloading django_formtools-2.1-py2.py3-none-any.whl (132kB) 100% |████████████████████████████████| 133kB 1.8MB/s Requirement already satisfied: Django>=1.8 in /usr/lib64/python3.6/site-packages (from django-formtools) Requirement already satisfied: pytz in /usr/lib/python3.6/site-packages (from Django>=1.8->django-formtools) Installing collected packages: django-formtools Successfully installed django-formtools-2.1 [root@localhost ~]#
まずは通常の SessionWizardView
urls.py
from django.conf.urls import url from myapp.forms import ContactForm1, ContactForm2 from myapp.views import ContactWizard urlpatterns = [ url(r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])), ]
オフィシャルを引用すると、普通の SessionWizardView は、こんな感じです。
urls.py でフォームを as_view() の引数に渡します。このフォームの数がページのステップ数になります。 ContactForm1 がステップ1ページで、ContactForm2 がステップ2ページ。
通常は、これで問題ないのですが、urls.py は Django の起動で、メモリに読み込まれるので、この方法では、動的にフォーム数(ステップ数)を変えることはできません。
フォームの中のフィールドは、__init__() に定義することで動的にすることはできます。
フォーム数(ステップ数)を動的にする SessionWizardView
urls.py
from django.conf.urls import url from myapp.forms import ContactForm1, ContactForm2 from myapp.views import contact_wizard urlpatterns = [ url(r'^contact/$', contact_wizard), ]
views.py
def contact_wizard(request): form_list = dynamic_form_list return ContactWizardView.as_view(form_list=form_list)(request)
通常の SessionWizardView と比べ、関数ベース View を間に1つ挟み、その関数ベース View の中で、動的にフォームのリストを生成します。
今回これが必要になった理由は、DBの値をみてフィールド数やフォーム数を変える必要があって、通常の SessionWizardView の方だと、DB の値を変更後に、Django を再起動する必要がありました。
しかし、この動的 SessionWizardView は、DB の値を変更するだけで、フィールド数やフォーム数を動的に変えることができます。
まとめ
Django の SessionWizardView で、Django の再起動なしで、動的にフィールド数、フォーム数(ステップ数、ページ数)を変える方法を説明しました。
formtools は、SessionWizardView の他に、入力->確認->完了 を作成するのに便利な FormPreview というものもありますので、機会があれば、説明したいと思います。