5

ステップのチェックボックスに基づいて条件付きで Django Formwizard (Django 1.4) のステップを繰り返そうとしています。フォームはオブジェクトを作成し、(うまくいけば) チェックボックスがあり、ステップを繰り返して、同じフォームで同じモデルの別のオブジェクトを作成できます。

私はこの答えを見ました:Django FormWizard Dynamically Alter form_listですが、残念ながらそれはFormWizardの古いバージョンにのみ適用されると思います。

process_step 関数には form_list 属性がなくなりました。また、現在のステップ属性 (またはステップ属性) もありませんが、フォームの QueryDict を介して現在のステップにアクセスできます。フォームのディクショナリが含まれていますが、そのディクショナリに別のステップを挿入しても何も起こらないと思います。残念ながら、リストではなくディクショナリであるため、挿入した場所の後にすべてのステップ キーを変更する必要があります。

では、Django 1.4 FormWizard を使用してフォーム リストに新しいステップを追加する良い方法はありますか?

更新 - get_next_step(self, step) をオーバーライドするのが良いと思い始めていますが、どんな意見でも大歓迎です。

更新 #2 -- get_next_step で作業を試みましたが、インスタンスの form_list に新しいフォームを挿入できませんでした。それが不可能だという意味ではありません - アイデアですか?

4

3 に答える 3

0

さて、私は何かを考え出した。get_form_list をオーバーライドしてフォーム リストに挿入できますが、フォーム リストを返すだけでなく、それらを self.form_list に保存する必要があります。私の目的では、これで問題ありませんが、conditional_dict も使用している場合は、ここで注意する必要があります。

def get_form_list(self):
    s = self.storage.current_step                                                                
    s_data = self.get_cleaned_data_for_step(s) or {}                                             
    add_another = s_data.get('add_another', False)                                   
    if add_another is True:                                                                      
        index = self.form_list.keyOrder.index(s)+1                                               
        key = "add_another-{0}".format(index)
        self.form_list.insert(index, key,                                                        
                wizard_forms.Wizard4)                                                   
    form_list = super(Wizard, self).get_form_list()
    return form_list

おそらくこれを少しきれいにするつもりですが、それが要点です。最初の数行は、現在のステップを取得し、このステップの後に別のステップを挿入するかどうかを決定するためのフラグを取得します。そのフラグが true の場合、フォーム内の現在のステップのインデックスを取得し、それに 1 を追加して、そのインデックスに挿入します (指定されたインデックスの前に挿入を挿入します)。インデックスに基づいたキーを使用して、ステップが何度繰り返されてもキーが重複しないようにします。次に、インスタンス全体になるように新しいステップを self.form_list に挿入し、(新しい self.form_list を持つ) self で get_form_list を呼び出し、必要に応じて form_list を返します。

注意事項:

  • 後者は無限再帰を引き起こすため、self.steps.currentではなくself.storage.current_stepを使用する必要があります。
  • 初期化後に self.form_list を使用しているという事実は、conditional_dict を使用している場合、少し面倒になる可能性があることを意味します。そうは言っても、 conditional_dict は条件にキーを割り当て、 form_list のキーはどれも変更されておらず、インデックスだけが変更されているため、そうではない可能性が非常に高いです。

それだけです!明らかに、これらのそれぞれを保存する方法を理解するために、done() にいくつかのロジックを追加する必要がありますが、それは何をしているかに固有のものです。

于 2012-10-25T15:00:22.750 に答える
0

評決は、それは不可能です。前の 2 つのソリューションでなぜうまくいったのかはよくわかりませんが、フォーム ウィザードのコードを掘り下げてみると、各リクエストがインスタンスのフォーム リストを再初期化することは明らかです (技術的には新しいインスタンスです) そのため、ストレージ内のリストをそのまま更新したり、get_form_list() で更新したりしても、get_form_list()を介してアクセスするのではなく、インスタンス変数を直接ヒットする呼び出しがいくつかあり、それを調整するには大きなリファクタリングが必要になります。

私はこのプロジェクトのために別のルートに行きましたが、すぐにこれのために何かをまとめようとするかもしれません.

于 2012-11-01T01:16:23.197 に答える
0

私が投稿した以前の回答はかなり一貫性がなく、奇妙なセッション衝突のバグだと思っていましたが、フォームを必要とするアクションに間に合うように get_form_list が常に呼び出されるとは限らないことが判明しました。同じロジックを get_next_step に移動したところ、スムーズに動作するようになりました。

def get_next_step(self, step=None):
    if step is None:
        step = self.steps.current
    s_data = self.get_cleaned_data_for_step(step) or {}
    add_another = s_data.get('add_another', False)
    if add_another is True:
        index = self.form_list.keyOrder.index(step)+1
        key = "add-another-{0}".format(index)
        self.form_list.insert(index, key,
                wizard_forms.Wizard4)
    return super(Wizard, self).get_next_step(step)
于 2012-10-26T16:42:49.163 に答える