Django + django-formtools SessionWizardView のフォーム数(ステップ数)を動的に変更する

シェアする

Django でウィザード形式のページを作りたいとき、SessionWizardView がとても便利ですね。SessionWizardView は、Django 1.7 まで django.contrib.formtools として組み込まれていましたが、Django 1.8 から別リポジトリ管理となりました。(なんででしょう?)

そんな SessionWizardView ですが、基本的な使い方でやるとフォーム数(ステップ数)が固定になります。それをどーしても動的にしたかったのですが、結構苦労したので、共有したいと思います。(何を言ってるのか全然わかりませんね・・・)

バージョン

  • 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 というものもありますので、機会があれば、説明したいと思います。

シェアする

フォローする