django 1.4 でフォーム ウィザードを使用して、最大 7 つのモデルのインスタンスを条件付きで追加しています。ユーザーがどのステップを完了するかに関係なく、最後のステップで、入力したすべてのデータのプレビューを表示したいと考えています。ユーザーは「最初のステップ」または「前のステップ」ボタンを使用して戻って、混乱したデータを修正できるため、フォームである必要はありません。また、すべてのデータを含む確認メールをユーザーに送信したいと思います。ここで思いついたソリューションは、そのためのデータも提供すると思います。
これが私が現在持っているものです:
# views.py
FORMS = [
('person_application', PersonApplicationForm),
('family_application', FamilyApplicationForm),
('student_application', StudentApplicationForm),
('spouse', SpouseForm),
('child', ChildFormSet),
('roommate', RoommateFormSet),
('preview', Form), # only doing this because I think FormWizard requires a Form subclass for every step, which makes sense
]
TEMPLATES = {
...
'preview': 'preview.html',
}
condition_dict = {
...
'preview': True,
}
class SignupWizard(SessionWizardView):
...
def get_context_data(self, form, **kwargs):
context = super(SignupWizard, self).get_context_data(form=form, **kwargs)
if self.steps.current == 'preview':
context.update({'all_data': self.get_all_cleaned_data()})
return context
# # This is triggering an infinite loop or something because python gets stuck at 100+% cpu and won't stop even when I kill runserver
# def get_form_initial(self, step):
# if step == 'preview':
# return self.get_all_cleaned_data()
# return {}
...
# urls.py
urlpatterns = patterns('app.views',
...
url(r'^start$', SignupWizard.as_view(FORMS, condition_dict=condition_dict, instance_dict=modelform_instances), name='wizard'),
url(r'^thanks$', 'thanks', name='thanks'),
)
ご覧のとおり、ある時点で実際にフォームをプレビューに使用しようと考えたので、WizardView.get_form_initial をオーバーライドしてみました。WizardView.get_all_cleaned_data() を使用して、すべてのデータをフォームの初期辞書として提供したいと考えていました。ただし、コメントで述べたように、これにより python がスタックし、手動でプロセスを見つけて強制終了し、停止する必要がありました。
そこで、WizardView.get_context_data() をオーバーライドして、ユーザーが入力したすべてのデータを含む追加のコンテキスト変数をテンプレートに送信しようと考えています (ここでも get_all_cleaned_data() を使用します)。ただし、これはいくつかの理由で少し複雑になります。同じ名前を持つモデルのフィールドは互いに影になるため、戻ってすべてのモデル フィールド名に名前を付ける必要があります。それは不必要に思えますが、何でも。また、私のフォームの 2 つは ModelFormSets であるため、それらのデータは辞書のリストとして提供されます。大したことではありませんが、テンプレートでの解析がより困難になります。この質問は長くなりますが、データを確認すると役立つ場合があります。そのため、get_all_cleaned_data() によって現在返されているものの例を次に示します (テンプレートに送信されるため)。
{'all_data': {'birthdate': datetime.date(1940, 2, 5),
'building_pref_1': u'NGH4',
'building_pref_2': u'K2',
'city': u'Nashville',
'country': u'',
'email': u'johnny@cash.com',
'first_name': u'Johnny',
u'formset-child': [{'birthdate': datetime.date(2013, 2, 3),
'gender': u'F',
'id': None,
'name': u'Rosanne'},
{'birthdate': datetime.date(2013, 2, 1),
'gender': u'F',
'id': None,
'name': u'Cathy'},
{'birthdate': datetime.date(2013, 2, 5),
'gender': u'F',
'id': None,
'name': u'Cindy'},
{'birthdate': datetime.date(2013, 2, 2),
'gender': u'F',
'id': None,
'name': u'Tara'},
{},
{}],
'furnishing': u'F',
'gender': u'F',
'global_id': u'',
'last_name': u'Cash',
'living_situation': u'SC',
'middle_initial': u'',
'move_in_date': None,
'move_out_date': None,
'name': u'Vivian Liberto',
'phone': u'9891111111',
'smoker_status': u'True',
'state_province': u'TN',
'street_1': u'street',
'street_2': u'',
'student_number': None,
'term': <Term: Summer 2013>,
'type': u'F',
'university_status': u'O',
'university_status_other': u'Travelling musician',
'zip_code': u''},
それで、私の質問は、私は正しい方向に進んでいますか、それともこれを行うためのより良い方法はありますか? たとえば、「プレビュー」ステップのフォームとして FormPreview サブクラスを使用し、FormPreview.done() を次のように定義します。
def done(self, request, cleaned_data):
pass
データが FormWizard の最終処理機構 (つまり、WizardView.done()) に渡されるようにするには?