Search code examples
pythondjangodjango-formsrequestdjango-formwizard

Django: How can I make Form Wizard take in a request object when it creates the forms?


How can I make it so that when Django's Form Tool's Wizard creates my forms, it also gives request object as a parameter? The main reason why I'm using Form Tool is to have a multi-page form. Right now to "normally" create my AnswerForm without the Wizard, it looks like

form = AnswerForm(request=request)

I'm taking in request because inside the form, I want to keep track of a key called 'question' in request.session. (The purpose of this key is to make sure that I can keep track of the Question model instance that is associated with the Answer instance that I'm trying to create through this form. I'm actually not sure if this is a good way to do this. Tips?) Anyway, right now I'm getting an error that seems to mean that somewhere in my ReviewWizard, request is not a parameter when the AnswerForm is created. I've read about how instance_dict can be used in the Wizard's as_view() in urls.py, but I don't think it would help in this case since the request object isn't available in urls.py. Can anyone help me with this? Or do you know of a better approach to do what I'm trying to do in general? Thanks for your help!!

(Ultimately the reason why I'm trying to keep track of Questions with Answers through request.session is because I think that when the first form a person sees shows up, it's a different instance from the form that gets POSTed. Since my setup() gets a random Question, it will probably not match up with the Question of the POSTed form, but maybe there's a better approach to all of this?? )

Line from urls.py:

url(r'^review_form/', ReviewWizard.as_view([AnswerForm, AnswerForm]), name='review_form'),

This is my form:

class AnswerForm(forms.Form):
    answer = forms.CharField(required=True)

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request')
        self.question = None
        self.setup()
        super(AnswerForm, self).__init__(*args, **kwargs)
        self.fields['answer'].label = self.question.question

    def setup(self):
        if "question" in self.request.session:
            self.question = Question.objects.get(id=self.request.session["question"])
        else:
            self.question = get_random_question()
            self.request.session["question"] = self.question.id

    def save(self):
        del self.request.session["question"]
        Answer.objects.create(
            question=self.question,
            author=self.request.user,
            answer=self.cleaned_data['answer']
        )

This is my Wizard Class in views.py (I copied it from elsewhere):

def process_form_data(form_list):
    form_data = [form.cleaned_data for form in form_list]

    print form_data[0]
    print form_data[1]

    return form_data
class ReviewWizard(SessionWizardView):
    template_name = "review_form.html"

    def done(self, form_list, **kwargs):
        form_data = process_form_data(form_list)

        return render("done.html", {"form_data": form_data})

Solution

  • You can use get_form_kwargs method from SessionWizardView to add your request into form kwargs.

    def process_form_data(form_list):
        form_data = [form.cleaned_data for form in form_list]
    
        print form_data[0]
        print form_data[1]
    
        return form_data
    class ReviewWizard(SessionWizardView):
        template_name = "review_form.html"
    
        def done(self, form_list, **kwargs):
            form_data = process_form_data(form_list)
    
            return render("done.html", {"form_data": form_data})
    
        def get_form_kwargs(self, step):
            kwargs = super(ReviewWizard, self).get_form_kwargs(step)
            kwargs['request'] = self.request
            return kwargs