Processing data between forms

If I have a 3-step registration this will use 3 forms.

Something like this, just to demonstrate:

@app.route('/form/step1', methods=['GET', 'POST'])
def form_step1():
    form = form_step_1(request.form)
    ...validate()...
    return render_template('register.html', form=form)

@app.route('/form/step2', methods=['GET', 'POST'])
def form_step2():
    form = form_step_2(request.form)
    ...validate()...
    return render_template('register.html', form=form)

@app.route('/form/step3', methods=['GET', 'POST'])
def form_step3(): 
    form = form_step_3(request.form)
    ...validate()...
    return render_template('register.html', form=form)

      

What is the correct way to process the data between these three steps? All data should be linked to the database at the end of step 3. But the reverse action between forms should re-fill the previous form.

Using sessions for this purpose seems bad.

+3


source to share


2 answers


I personally would suggest using the session object to transfer data from one form to another. If you have a small amount of data, you can get away by simply using the implementation of the cookies that the flask has. Otherwise, you can override the default session object to store sessions on the data server side using Redis. This allows session objects to be used without paying the cost of storing large amounts of data in cookies. This means that you can do something like



@app.route('/form/step1', methods=['GET', 'POST'])
def form_step1():
    form1 = form_step_1(request.POST)
    user_id = current_user.user_id # If you're using flask-login
    ...validate()...
        # dictionary that holds form1, form2, etch
        form_data = {"form1": form1, "form2": None, "Form3"=None} 
        flask.session[user_id] = form_data
        redirct_to(url_for("form_step2"))
    return render_template('register.html', {'form':form1})  

@app.route('/form/step2', methods=['GET', 'POST'])
def form_step2():
    form1 = session[user_id][form1]
    # A simpler way than passing the whole form is just the data 
    # you want but for this answer I'm just specifying the whole form.
    form = form_step_2(form1)
    user_id = current_user.user_id # If you're using flask-login 
    ...validate()...
        # dictionary that holds form1, form2, etch
        flask.session[user_id]["form2"] = form2
        redirct_to(url_for("form_step3"))
    return render_template('register.html', form=form)

      

+3


source


If you have no reason to worry about POST holding your form data, you can use hidden form fields in the second and third submissions to transfer the data. Think about it...

forms.py
# override EACH form init to change the widget for each field to a hidden widget if is_hidden kwarg passed. 

class form_step_1(forms.Form):

    def __init__(self, *args, **kwargs):
        is_hidden = kwargs.pop('is_hidden', None)
        super(FormName, self).__init__(*args, **kwargs)
        if is_hidden:
            for field in self.fields:
                self.fields[field].widget = forms.HiddenInput()

# Be sure to do this for each form with hidden input needed


views.py

@app.route('/form/step1', methods=['GET', 'POST'])
def form_step1():
    form1 = form_step_1(request.POST)
    ...validate()...
    return render_template('register.html', {'form':form1})  

@app.route('/form/step2', methods=['GET', 'POST'])
def form_step2():
    form1 = form_step_1(request.POST, is_hidden=True)
    hidden_forms =[form1]
    form2 = form_step_2(request.POST)
    ...validate()...
    return render_template('register.html', {'form':form2, 'hidden_forms':hidden_forms})

@app.route('/form/step3', methods=['GET', 'POST'])
def form_step3(): 
    form1 = form_step_1(request.POST, is_hidden=True)
    form2 = form_step_2(request.POST, is_hidden=True)
    hidden_forms =[form1, form2]
    form = form_step_3(request.form)
    ...validate()...
    if form.is_valid():
        # do stuff, save to DB
        form1.save()
        form2.save()
        form3.save()
        return HttpReturnRedirect('/success_page/') # Always Redirect after posting form
    # if not valid, show again.
    return render_template('register.html', {'form':form, 'hidden_forms':hidden_forms })


template.html (assuming you are using a single template for each page

<form action="." etc>
    {% csrf_token %}
    {{ form }}
    {% for each_form in hidden_forms %}
        {{ each_form }}

    <!-- your submit button -->
</form>

      



Now when your form goes to POST in step 3, if valid, all the form data from the previous steps is available.

If you want to find a reckless solution (requires a bit more work) take a look at Django FormWizard

0


source







All Articles