Web 应用程序:Flask - html - wtforms:带有两个提交按钮的表单

Web application: Flask - html - wtforms: form with two submit buttons

我是编程新手。我有兴趣开发一个具有两个输入值和两个提交按钮的简单网络应用程序。数字 A 和 B 由用户输入,产品或总和将根据按下的按钮显示。当我使用一个按钮时,代码有效;但是,我似乎无法弄清楚如何使这两个按钮都起作用。我在 Flask 和 Python 3.8 中编写了应用程序并使用了 wtforms。

这是我的代码: view.html



<table>
  {% for field in form %}
    <tr>
    <td>{{ field.name }}</td><td>{{ field }}</td>
    <td>{{ field.label }}</td>
    </tr>
  {% endfor %}
</table>

<form method="post" action="">
<input type="submit" name="btn" value="Add">
</form>
<p>
<form method="post" action="">
<input type="submit" name="btn" value="Multiply">
</form></p>

<p>
{% if result != None %}
{{result}}
{% endif %}
</p>

Python代码 views.py


@app.route("/comp", methods=['GET', 'POST'])
def comp():
    form = InputForm(request.form)
    if request.method == 'POST' and form.validate():
        if request.form["btn"] == "Add":
            result = add(form.A.data, form.B.data)
        
        elif request.form["btn"] == "Multiply":
            result = mul(form.A.data, form.B.data)
    else: result = None
    return render_template('view.html', form=form, result=result)

我在一个单独的文件中定义了 mul() 和 add() 函数,因为我计划在未来进一步扩展该应用程序。这是函数定义:


def mul(A,B):
    return  A*B
def add(A,B):
    return  A+B

我的 input.py 文件:

from wtforms import Form, FloatField, validators

class InputForm(Form):
    A = FloatField(
        label='A', default=0,
        validators=[validators.InputRequired()])
    B = FloatField(
        label='B', default=0,
        validators=[validators.InputRequired()])

您的一个值是“ADD”,但您测试的是“Add”。所以,相等性测试失败

更新:

你在哪里定义add()mul()?也许改为使用:

if request.form['btn'] == 'Add':
    result = form.A.data + form.B.data

elif request.form['btn'] == 'Multiply':
    result = form.A.data * form.B.data

更新2:

试试这个来诊断:

if request.method == 'POST' and form.validate():
    print(request.form["btn"])
    print(form.A.data, form.B.data)
    print(request.POST)

如果我理解这个问题,请尝试这样做:

from flask import render_template、重定向、url_for、flash、请求

@app.route('/comp') #sample only
def comp():

    form = InputForm(request.form)
    if request.method == 'POST' and form.validate()
        if request.form['btn'] == 'Add':
            result = add(form.A.data, form.B.data)

        elif request.form['btn'] == 'Multiply':
            result = mul(form.A.data, form.B.data)
        flash(result) # see the result in the browser
        print('result') # see the result in the terminal
        return redirect(url_for('comp'))
    else:
        result = None
    return render_template('view.html', form=form, result=result)

要在 html 中实现 flash,只需在某处添加这个

{% for msg in get_flashed_messages()%}
   <h1> {{msg}} </h1>
{% endfor %}

为了解决问题,我总是添加打印语句和闪光灯,以便查看问题出在哪里。

您有 3 种不同的形式。 AB 不属于您提交的任何一种形式。

好的,我对您的代码进行了故障排除。首先这是结果:

Flask Code :

from flask import Flask, request, render_template, url_for, flash, redirect
from wtforms import SubmitField, Form, FloatField, validators


app = Flask(__name__)

app.config['SECRET_KEY'] = 'dev'

def mul(A,B):
    return  A*B
def add(A,B):
    return  A+B

# Form
class InputForm(Form):
    A = FloatField(
        label='A', default=0,
        validators=[validators.InputRequired()])
    B = FloatField(
        label='B', default=0,
        validators=[validators.InputRequired()])
   
       
       
@app.route('/comp', methods=['GET', 'POST'])
@app.route('/', methods=['GET', 'POST']) #this so that both url will work
def comp():

    result = ''   #already assign a variable, else will throw error
    form = InputForm(request.form)
    if request.method == 'POST': #First we check if method is post **POINT 2**
            if form.validate(): #Then if form is validate
                print('form ok') #Test if form is ok
                if request.form['btn'] == 'Add':
                    result = add(form.A.data, form.B.data)
                    print(result) 
            
                elif request.form['btn'] == 'Multiply':
                    result = mul(form.A.data, form.B.data)
                    print(result)
                
                flash(result) # **POINT 3**
                return redirect('comp') # This will make your code run forever #**4**     
            else:
                print('form no ok ') #check if form no ok
    else:
        print('request is get') # if you put the form.validate with the method condition, the form will return False as soons as you render the template

    return render_template('view.html', form=form, result=result)


if __name__ == '__main__':
    app.run(debug=True)

HTML file:

  <form method="post" action="">
      <table>
        <!-- Generates form fields -->
        <!-- POINT 1 -->
        {% for field in form %}  

            <td>{{ field.name }}</td><td>{{ field }}</td>
            <td>{{ field.label }}</td>
          </tr>
          
        {% endfor %}
        
        <tr>
          <!-- Input are inside the form tag -->
          <td><input type="submit" name="btn" value="Add"></td>
          <td><input type="submit" name="btn" value="Multiply"></td>

        </tr>
      </table>
    </form>

<!-- Print result in the browser  -->
<!-- Needs to redirect to the same page -->
<!-- return redirect('comp')    -->

  {% for msg in get_flashed_messages()%}
  <h1>   {{msg}} </h1> 
  {% endfor%}
  1. So the main issue was that in the HTML the form is not together with the input field, hence it was elaborating the form separately. By adding all together then it will start to work.
  1. In the python file, the if request.method == 'POST' condition run simultaneously with the form hence returning the form False even before submit it.

.3 Added a Flash method so that you can see the result

.4 Add a redirect, this will flash the result to the browser, but most importantly will refresh the form and gives you possibility to add a new one.

请注意,重定向页面也很重要,因为想象一下,如果您想将其提交到数据库中,这将使您提交表单并保存更改。