2014-10-17 64 views
3

如果我有3个步骤的注册,那将使用3个表格。处理表格之间的数据

这样的事情,只是为了演示:

@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) 

什么是处理这三个步骤之间数据的正确方法是什么?所有数据应在步骤3结束时提交给数据库。但表单之间的后退操作应该再次填充先前的表单。

为此目的使用会话看起来很糟糕。

+0

为什么不在每一步的结尾之前将它们存储到数据库? – 2014-10-17 09:12:09

+0

@ m170897017这是一种可能性,但有点无聊。在这种情况下,我需要多次更新相同的注册表。在这个例子中,第2步和第3步只是sql更新吧? – user455318 2014-10-17 09:20:39

+0

您可以将表单的内容存储在某些类变量中,并在步骤3结束时将它们保存到数据库中? – 2014-10-17 09:28:31

回答

3

我个人建议使用会话对象从一种形式传递到另一个数据。如果你有少量的数据,那么你只需使用烧瓶所具有的cookie实现就可以逃脱。否则,you can override the default sessions object to store sessions data server side using Redis. This lets you use session objects without paying the price of storing lots of data in cookies.这意味着你可以做类似于

@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) 
+0

另一种方法,可能我可以使用[flask-redis](https://github.com/rhyselsmore/flask-redis)临时存储每个步骤的数据。 Redis是为此而制作的。 – user455318 2014-10-22 17:10:38

+0

我完全同意。我个人喜欢使用会话对象,因为我的应用程序已经从会话中检索数据,并且它看起来像这样一致。但使用flask-redis是一个完全有效的选择。 – AlexLordThorsen 2014-10-22 21:06:22

+0

我得到错误,我的表单“不是JSON可序列化”你如何克服这一点? – user805981 2016-02-02 05:51:27

0

如果您没有任何理由担心POST表劫持您的表单数据,您可以在第二个和第三个视图中使用隐藏表单字段来传递数据。想想沿着这些路线...

forms.py 
# override EACH form's 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> 

现在,当您的表单在步骤3中转到POST后,如果有效,每个表单的前几步的数据都可用。

如果你想要一个鲁莽的解决方案(即需要多一点的工作),看看Django FormWizard

+2

隐藏的表单看起来比会话更差。无论如何,我正在谈论烧瓶和wtforms,而不是django。 – user455318 2014-10-20 08:11:42