6

シンプルな 2 部構成の FormWizard を実装したいと考えています。フォーム 1 は、次のように動的に生成されます。

class BuyAppleForm(forms.Form):
   creditcard = forms.ChoiceField(widget = forms.RadioSelect)
   type = forms.ChoiceField(widget = forms.RadioSelect)
   def __init__(self,*args, **kwargs):
        user = kwargs['user']
        del kwargs['user']

        super(BuyAppleForm, self).__init__(*args, **kwargs)

        credit_cards = get_credit_cards(user)
        self.fields['creditcard'].choices = [(card.id,str(card)) for card in credit_cards]

        apple_types= get_types_packages()
        self.fields['type'].choices = [(type.id,str(type)) for type in apple_types]

これにより、利用可能な選択肢のリストを含むフォームが動的に作成されます。

私の 2 番目のフォームでは、実際には何も入力したくありません。クレジット カード情報、Apple 情報、および金額 (合計、税、送料) を含む確認画面を表示したいだけです。ユーザーが [OK] をクリックしたら、リンゴの購入を開始します。

kwargs で request.user オブジェクトを渡すことで、単一のフォームの方法を実装できました。しかし、FormWizard では、これがわかりません。

私は問題に間違ってアプローチしていますか? FormWizard はこれを行う適切な方法ではありませんか? __init__そうである場合、Formメソッドは HTTP 要求からユーザー オブジェクトにどのようにアクセスできますか?

4

5 に答える 5

4

FormWizard を理解しようとしていたとき、あちこちを検索したところ、ほとんどの場合、使用しないでくださいというような回答が見つかりました。OPは1レベルのフォームにのみ関心があるため、FormPreviewは正常に機能しますが、FormWizardの使用方法については依然として有効です。

この質問は非常に古いものですが、ここで回答することは価値があると思います。なぜなら、この質問は非常に多くのサイトで尋ねられており、それに対するまとまりのある回答も、ドキュメントに明確な解決策も見当たらないからです。

OPの質問に関しては、process_stepをオーバーライドするのが道だと思います。トリックは、最初のフォームからデータを受け取るこのメソッド内でフォーム (またはビュー) を作成することです。

この form_setup を forms.py にユーティリティ ラッパーとして追加しました (コンストラクターと考えてください)。

def form_setup(**kwargs):
    def makeform(data, prefix=None, initial=None):
        form = FormLev2(data, prefix, initial)
        for k, v in kwargs.items():
            if k == 'some_list':
                form.fields['some_list'].choices = v
            ...
        return form
    return makeform

次に、次のように process_step をオーバーライドします。

def process_step(self, request, process, step):
    if step == 1
        if form.is_valid():  #form from step 1
            objs = Table.objects.filter(...) #based on last form 
            self.form_list[1] = form_setup(some_list=[(o.id,o.name) for o in objs])  #(*)
    ...

そうすれば、フォーム定義自体ではなく、FormWizard インスタンスの form_list を変更するという意味で、form_list(*) を動的に変更できます。ラッパー関数は、新しい Form オブジェクトをインスタンス化する関数を返すため、この機能に不可欠です。これは、FormWizard 内で使用され、次のフォームのデータで呼び出され、前のフォームのデータを使用できるようにします。 .

編集:エリックのコメントのために、そして最後の部分を明確にするために。

また、process_step は、ステップ n の後にステップ [0,n] で呼び出されることに注意してください。

于 2011-02-01T01:39:11.620 に答える
4

私は使っていませんが、ご指摘の状況では、FormWizardの代わりにFormPreviewを試してみたいと思われるかもしれません。ドキュメントから、あなたが求めているもののように聞こえます。

于 2008-12-11T12:14:22.403 に答える
0

自分の質問に答えることがStackOverflowで許容できる動作であるかどうかはわかりません。これが、自分の問題に対する私の解決策です。

まず、FormWizardを捨てます。

私には1つのフォームがあります。2つのビュー:buy_applesおよびbuy_apples_confirm

最初のビューはGETのみを処理します。2番目のビューのURLに移動するアクションを使用して、バインドされていないフォームを出力します。

2番目のビューは、「confirm」という名前のPOSTパラメーターの存在をチェックします。存在しない場合(ビューが最初にロードされたときではないため)、次のようになります。

  1. すべてのフィールドのウィジェットをHiddenInputになるように調整します
  2. 注文の概要を示すテンプレートを書き出します。このテンプレートは、「確認」と呼ばれる非表示フィールドも1に設定します(このフィールドはフォームに存在しませんが)

ユーザーがクリックしてリンゴを購入すると、フォームが送信され、buy_apples_confirmビューがもう一度呼び出されます。今回は「confirm」というPOSTパラメータが存在するため、実際に購入トランザクションを処理し、ユーザーがリンゴを入手します。

この方法や状況に対処するためのより良い方法についての批評を歓迎します。私はDjangoを初めて使用し、問題に取り組むにはさまざまな方法があることに気付きました。でも最高から学びたいです。

于 2008-12-11T06:18:07.600 に答える
0

呼び出しメソッドを変更して、追加のパラメーターを取得するのはどうですか?

これに似たもの: http://dw.me/blog/2010/3/18/15/

于 2010-05-03T02:38:48.577 に答える
0

あなた自身の質問に答えてくれてありがとうkrys。助かりましたが、まだコメントがありました。

FormPreview は、私が知る限り動的フォームをサポートしていないため、進むべき道ではありません。そこから from を生成するために、固定フォーム クラスに依存しています。しかし、ここでは関数を使用して動的に生成しています。たぶん、FormPreview はいつかこれをサポートするでしょう (または既にサポートしており、その方法はわかりません)。

Krys のソリューションは FormPreview と同じようです。ハッシュのみが省略されているため、ユーザーは非表示フィールドのデータを変更できますか、それとももう一度確認しますか?. もう一度チェックすると、チェックを複製するため、DRY には従いません (わかりました。再利用可能な方法である可能性があるため、ごくわずかな繰り返しのみです)。

私が疑問に思っていたのは、ウィジェットをどのように調整するのですか? 新しいウィジェットでフォームを複製しますか、それとも動的に変更する方法はありますか?

于 2009-03-12T10:43:10.763 に答える