Django FormWizard with dynamic forms

后端 未结 5 1986
既然无缘
既然无缘 2021-02-04 18:48

I want to implement a simple 2 part FormWizard. Form 1 will by dynamically generated something like this:

class BuyAppleForm(forms.Form):
   creditcard = forms.C         


        
5条回答
  •  天命终不由人
    2021-02-04 19:36

    When I was trying to figure out FormWizard, I searched all over and found responses such as most of these that just say don't use it. FormPreview would work fine since OP is only interested in a one-level form, but the question is still valid in how to use FormWizard.

    Even though this question is so old, I think it is valuable to answer here because this question is asked on so many sites and I see no cohesive response to it, nor a clear solution in the docs.

    I think in terms of the OPs question, overriding process_step is the way to go. The trick is in creating the form (or view) within this method that will receive the data from the first form.

    I added this form_setup to my forms.py as a utility wrapper (think constructor):

    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
    

    Then override process_step as follows:

    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])  #(*)
        ...
    

    That way, you are able to dynamically modify form_list(*), in the sense that you modify the form_list in the FormWizard instance, rather than the form definitions themselves. The wrapper function is essential for this functionality, as it returns a function that will instantiate a new Form object, which is then used within FormWizard to be called with the data for the next form, and allows you to use the data from the previous one.

    Edit: for Erik's comment, and to clarify the last part.

    Also note that process_step will be called with step [0,n] after step n.

提交回复
热议问题