Flask的多个表单一直在说我还没有定义表单

时间:2018-04-16 11:56:11

标签: python flask flask-wtforms

我正在尝试使用验证器在同一个Flask页面上设置两个不同的表单,但它一直告诉我我的表单没有定义。我收到错误:

该代码旨在允许用户输入一个数字并检查它是否丰富,完美或不足,然后使用单独的表单允许用户定义范围并获得有多少丰富,完美或不足的数字在这个范围内。

我的代码如下:

from flask import Flask, render_template, request
from flask_wtf import Form
from wtforms import IntegerField
from wtforms.validators import InputRequired
from perfect_numbers import classify, listInRange

app = Flask(__name__)
app.config['SECRET_KEY'] = 'DontTellAnyone'

class PerfectForm(Form):
    inputNumber = IntegerField('input a number', default=1, validators=[InputRequired(message='Please input an integer')])

class PerfectRangeForm(Form):
    startNumber = IntegerField('input a number', default=1, validators=[InputRequired(message='Please input an integer')])
    endNumber = IntegerField('input a number', default=1, validators=[InputRequired(message='Please input an integer')])

@app.route('/', methods=['GET', 'POST'])
def index():
    form1 = PerfectForm(request.form, prefix="form1")
    num = 1
    Classify = classify(num)
    if form.validate_on_submit() and form.data:
        num = request.form1['inputNumber']
        Classify = classify(form1.inputNumber.data)
        return render_template('index.html', form1=form1, num=num, classify=Classify)
    return render_template('index.html', num=1, form1=form1, classify=Classify)

@app.route('/aliRange', methods=['GET', 'POST'])
def aliRange():
    form2 = PerfectRangeForm(request.form2, prefix="form2")
    startNumber = 1
    endNumber = 1
    aliquot = 'abundant'
    Classify = classify(num)
    ListInRange = listInRange(startNumber, endNumber, aliquot)
    if form2.validate_on_submit() and form2.data:
        startNumber = request.form2['startNumber']
        endNumber = request.form2['endNumber']
        aliquot = request.form2['aliquot']
        ListInRange = listInRange(startNumber, endNumber, aliquot)
        return render_template('index.html', form2=form2, startNumber=startNumber, endNumber=endNumber, ListInRange=listInRange)
    return render_template('index.html', form2=form2, startNumber=startNumber, endNumber=endNumber, ListInRange=listInRange)

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

的index.html:

{% from "_formhelpers.html" import render_field %}
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>WTForms</title>
  </head>
  <body>
    <div>
      <form action="/" method="POST">
        <dl>
          {% if form1 %}
          {{ form1.csrf_token }}
          {{ render_field(form1.inputNumber) }}
          {% endif %}
          <input type="submit" value="submit1">
        </dl>
      </form>
    </div>
    <div>
      {{ num }} is {{ classify }}
    </div>

    <div></div>

<div>
  <form action="/aliRange" method="POST">
    <div class="form-group">
      <p>Input a start number and an end number to return a list of...</p>
      <select class="form-control" action="/aliRange" name="aliquot" method="POST">
        <option value = 'abundant'>Abundant</option>
        <option value = 'perfect'>Perfect</option>
        <option value = 'deficient'>Deficient</option>
      </select>
      <p>...numbers within that range</p>
      <form action="/aliRange" method="POST">
        <dl>
          {% if form2 %}
          {{ form2.csrf_token }}
          {{ render_field(form2.startNumber) }}
          {{ render_field(form2.endNumber) }}
          {% endif %}
          <input class="btn btn-primary" type="submit" value="submit">
        </dl>
      </form>
    </div>

  </form>
  The {{ aliquot }} numbers between {{ startNumber }} and {{ endNumber }} are:
  {{ listInRange }}
</div>
  </body>
</html>

我得到的错误是:AttributeError:&#39;请求&#39;对象没有属性&#39; form1&#39;

1 个答案:

答案 0 :(得分:0)

编辑:

您可以使用单个视图简化代码,使用submit值来区分第一个表单和第二个表单的处理。

修改后的代码是:

class PerfectForm(Form):
    inputNumber = IntegerField('input a number', default=1, validators=[InputRequired(message='Please input an integer')])

class PerfectRangeForm(Form):
    startNumber = IntegerField('input a number', default=1, validators=[InputRequired(message='Please input an integer')])
    endNumber = IntegerField('input a number', default=1, validators=[InputRequired(message='Please input an integer')])
    aliquot = StringField('input a kind', default='perfect')

@app.route('/', methods=['GET', 'POST'])
def index():
    form1 = PerfectForm(request.form, prefix="form1")
    form2 = PerfectRangeForm(request.form, prefix="form2")

    num = 1
    Classify = classify(num)

    startNumber = 1
    endNumber = 1
    aliquot = 'abundant'
    ListInRange = listInRange(startNumber, endNumber, aliquot)

    if request.form.get('submit') == 'submit-1':
        if form1.validate_on_submit() and form1.data:
            num = form1.data['inputNumber']
            Classify = classify(num)
    elif request.form.get('submit') == 'submit-2':
        if form2.validate_on_submit() and form2.data:
            startNumber = form2.data['startNumber']
            endNumber = form2.data['endNumber']
            aliquot = form2.data['aliquot']
            ListInRange = listInRange(startNumber, endNumber, aliquot)
    return render_template('index.html',
        num=num, classify=Classify,
        startNumber=startNumber, endNumber=endNumber, aliquot=aliquot, ListInRange=ListInRange,
        form1=form1, form2=form2)

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

,修改后的模板index.html为:

{% from "_formhelpers.html" import render_field %}
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>WTForms</title>
  </head>
  <body>
    <div>
      <form action="/" method="POST">
        <dl>
          {{ form1.csrf_token }}
          {{ render_field(form1.inputNumber) }}
          <input type="submit" name="submit" value="submit-1">
        </dl>
      </form>
    </div>
    {% if num %}
    <div>
      {{ num }} is {{ classify }}
    </div>
    {% endif %}

    <hr />

    <div>
      <form action="/" method="POST">
        {{ form2.csrf_token }}
        <div class="form-group">
          <p>Input a start number and an end number to return a list of...</p>
          <select class="form-control" action="/aliRange" name="aliquot" method="POST">
            <option value = 'abundant'>Abundant</option>
            <option value = 'perfect'>Perfect</option>
            <option value = 'deficient'>Deficient</option>
          </select>
          <p>...numbers within that range</p>
          <dl>
          {{ render_field(form2.startNumber) }}
          {{ render_field(form2.endNumber) }}
          </dl>
          <input class="btn btn-primary" type="submit" name="submit" value="submit-2">
        </div>
      </form>
      <div>
        The {{ aliquot }} numbers between {{ startNumber }} and {{ endNumber }} are:
        {{ listInRange }}
      </div>
    </div>
  </body>
</html>

OLD:

您在模板中使用了form1,但在模板上下文中传递了form

render_template('index.html', form=form1, num=num, classify=Classify)

您可以在模板中将form1更改为form,也可以在上一行中传递form1=form1

如果要在同一模板中渲染多个表单,则必须从呈现该模板的所有视图中传递所有相应的表单变量:form1form2,....否则,模板渲染将引发您看到的错误。

如果您对在模板中所有可能的表单中呈现单个表单感兴趣,可以使用

进行条件渲染
{% if form1 %}
<div>
  <form action="/" method="POST">
    <dl>
      {{ form1.csrf_token }}
      ...
    </dl>
  </form>
</div>
{% endif %}

{% if form2 %}
<form action="/aliRange" method="POST">
...
</form>
{% endif %}

...

另外,你的html对我来说似乎不对,因为你有一个嵌套在另一个表单中的表单。不确定你想要在那里获得什么。