2012-04-05 11 views
5

Django 1.4の新しいフォームウィザード機能を使用してウィザードを構築しています。
これに関するドキュメントは非常に簡潔であり、高度な例は見つかりません。名前付きステップウィザード(私たちが使用するリストビュー/データグリッドをサポートするために必要)とセッションバックエンドを使用しています。 ウィザードは役割とリンクされた権限を編集するためのもので、追加機能と編集機能の両方を提供するように構築されています。最初の手順でユーザーに追加または編集したいかどうかを尋ねることで、これを行います。Django 1.4フォームウィザードの使用に関する明確化が必要、具体的には事前充填と保存

次のステップはその選択に依存します。 ユーザーが編集したい場合は、検索画面があり、結果が表示されるlistview/datagridが続きます。ユーザーは結果の1つを選択して詳細画面に進み、FilteredSelectMultipleページを表示し、このロールに権限をリンクすることができます。

ユーザーが新しい役割を追加したい場合、検索画面と結果画面はスキップされ、ユーザーは詳細画面に直接続き、リンク画面が表示されます。
それはすべてのurls.pyにcondition_dictを使用して、かなりうまく動作しますが、我々は一般的な機能について、物事のカップルを不思議に思っている:

特定の既存の役割を選択した場合、どのように我々は埋めることができます詳細と対応するデータとのリンク画面?

ロールオブジェクトをインスタンス化して、2つのフォームに何らかの形で渡しますか?もしそうなら、インスタンス化する場所と、フォームごとに別々に行う必要がありますか?

保存するときに、ロールオブジェクトの別のインスタンスを作成し、フォームデータを追加して保存したり、フォームで使用されているオブジェクトを何らかの形で再利用できますか?

私たちは、役割のインスタンスを返すためにget_form_instanceの過負荷を試してみましたが、私たちはドキュメントにinstance_dict見てきましたが、それは間違ったアプローチのように感じていると、オンラインで発見されるいかなる例が存在しない、と私たちはしていますたとえこれらがデータのプリフィルに使用されていても、正しいトラックにいても確実ではありません。

論理的には、既存のロールを選択するステップでは、選択したオブジェクトのインスタンスを使用してウィザード変数を入力する必要があり、これらがフォームに表示されます。ウィザードの最後に、プロセスを逆転させ、ウィザード変数からすべてのデータを取得し、新しくインスタンス化されたロールオブジェクトに追加して保存します。このインスタンスは、PRERTUREキーが満たされているかどうかに応じて、INSERTまたはUPDATEを実行する必要がある場合は、理想的にはそれ自体を決定します。

誰かが例を挙げることができますか、正しい方向に微妙な動きがある場合は、非常に感謝しています。

views.pyでwizardviewクラスのコードは以下の通りです:

class RolesWizard(NamedUrlSessionWizardView): 

def get_template_names(self): 
    # get template for each step... 
    if self.steps.current == 'choice': 
     return 'clubassistant/wizard_neworeditrole.html' 
    if self.steps.current == 'search': 
     return 'clubassistant/wizard_searchrole.html' 
    if self.steps.current == 'results': 
     return 'clubassistant/wizard_pickrole.html' 
    if self.steps.current == 'details': 
     return 'clubassistant/wizard_detailsrole.html' 
    elif self.steps.current == 'rights': 
     return 'clubassistant/wizard_roles.html' 

def get_context_data(self, form, **kwargs): 
    # get context data to be passed to the respective templates 
    context = super(RolesWizard, self).get_context_data(form=form, **kwargs) 

    # add the listview in the results screen 
    if self.steps.current == 'results': 
     # get search text from previous step 
     cleaned_data = self.get_cleaned_data_for_step('search') 
     table = RolesTable(Roles.objects.filter(
      role_name__contains=cleaned_data['searchrole']) 
     ) 
     RequestConfig(self.request, paginate={ 
      "per_page": 4, 
      }).configure(table) 
     # add the listview with results 
     context.update({'table': table}) 

    # add a role instance based on the chosen primary key 
    if self.steps.current == 'rights': 
     cleaned_data = self.get_cleaned_data_for_step('results') 
     role_id = cleaned_data['role_uuid'] 
     role = get_object_or_404(Roles, pk=role_id) 
     context.update({'role': role}) 

    return context 

def done(self, form_list, **kwargs): 
    # this code is executed when the wizard needs to be completed 

    # combine all forms into a single dictionary 
    wizard = self.get_all_cleaned_data() 

    if wizard.get("neworeditrole")=="add": 
     role = Roles() 
    else: 
     role = get_object_or_404(Roles, pk=wizard.get("role_uuid")) 

    # many-to-many rights/roles 
    role.role_rights_new_style.clear() 
    for each_right in wizard.get('role_rights_new_style'): 
     RightsRoles.objects.create(role=role, right=each_right,) 

    # other properties 
    for field, value in self.get_cleaned_data_for_step('details'): 
     setattr(role, field, value) 

    role.save() 

    # return to first page of wizard... 
    return HttpResponseRedirect('/login/maintenance/roles/wizard/choice/') 

答えて

1

は、私は助けることができるかどうか見てみましょう。答えに応じてステップを追加するフォームウィザードを実行しました。各ステップで私はそうのように、セッション変数にすべてのフォームを保存します。

def process_step(self, request, form, step): 
    request.session['form_list'] = self.form_list 
    request.session['initial'] = self.initial 

その後、レンダリングされるビューたびに、私は、以前のすべてのデータを新しいフォームウィザードをインスタンス化:

def dynamic_wizard(request): 
    if not request.session.get('form_list'): 
     form = Wizard([Form1]) 
    else: 
     form = Wizard(request.session.get('form_list'), initial = request.session['initial']) 
    return form(context=RequestContext(request), request=request) 
+0

これはdjango 1.3です。 – daigorocub

2

将来のgooglerの場合:

フォームがレンダリングされる前に呼び出されるため、get_form()を使用していくつか成功しました。あなたのSessionWizardViewで、

class Wizard1(models.ModelForm): 
    class Meta: 
     model = MyModel 
     fields = ('field0', 'model0') 
class Wizard2(models.ModelForm): 
    class Meta: 
     model = MyModel 
     excludes = ('field0', 'model0') 

その後:ModelFormsのカップルと開始

class MyWizard(SessionWizardView): 
    def get_form(self, step=None, data=None, files=None): 
     form = super(ExtensionCreationWizard, self).get_form(step, data, files) 

     if step is not None and data is not None: 
      # get_form is called for validation by get_cleaned_data_for_step() 
      return form 

     if step == "0": 
      # you can set initial values or tweak fields here 

     elif step == "1": 
      data = self.get_cleaned_data_for_step('0') 
      if data is not None: 
       form.fields['field1'].initial = data.get('field0') 
       form.fields['field2'].widget.attrs['readonly'] = True 
       form.fields['field3'].widget.attrs['disabled'] = True 
       form.fields['model1'].queryset = Model1.objects.filter(name="foo") 

     return form 

をアクションは、すべてあなたがget_formする別のコールをトリガーステップ0(からのデータを検証要求するステップ1です( )ステップ0のため、注意してください)その後、ステップ0で設定された値にアクセスできます。

フィールドで変更できる設定の例をいくつか投げました。 ChoiceFieldの値を制限するためにクエリーセットを更新することも、値をもう一度表示し直して読み取り専用にすることもできます。私が気付いた1つの注意点... readonlyはChoiceFieldで動作しません。無効にすることはできますが、フォームを送信するときに値は伝播されません。

+0

これはこれを行う方法です! – JeffC

+0

html、 "get_form"メソッドは、フォーム関連のものはフォームクラスそのものに保持する必要があるので、私の意見では不幸です。より良い方法は、get_form_kwargsを使用して "flags"を設定し、それを使用してフォーム初期化メソッド内のフィールドをカスタマイズすることです。 – mariodev

関連する問題