Python - Flask验证SelectField

时间:2017-05-29 12:42:32

标签: python validation google-app-engine flask flask-wtforms

我是python世界中的小说,我试图使用谷歌苹果引擎的外部API,我想用一个填充了Api的json响应的selectField进行表单验证。

这是我的代码

class CommentForm(FlaskForm):
    name = StringField('Nome', [required()])
    nazionalita = SelectField('Nazionalita',[required()])
    eta = IntegerField('Eta', [required()])
    Comment = TextAreaField('Commento', [required()])
    Data = DateTimeField('Data',[required()],format='%d/%m/%Y', )
    submit = SubmitField('Inserisci', [required()])

    def validate_nazionalita(form):
       if  not form.nazionalita.data == None:
          raise ValidationError('Nazionalita non selezionata')

@app.route('/insert', methods=['GET'])
def insert():
    form = CommentForm()
    url = 'https://ajayakv-rest-countries-v1.p.mashape.com/rest/v1/all'
    req = urllib2.Request(url)
    req.add_header('X-Mashape-Key', MASHAPE_KEY)
    req.add_header('Accept', 'application/json')
    urlresponse = urllib2.urlopen(req)
    content = urlresponse.read()

    responde = make_response(content)

    responde.headers['content-type']='application/json'
    data = json.loads(responde.data)
    nation = list(data)
    scelte =[]
    scelte =  ([( s['callingCodes'] , s['name'] )for s in nation])
    form.nazionalita.choices= scelte
    return  render_template('insert.html', form=form)


@app.route('/insert', methods=['POST'])
def submit():
    form = CommentForm(request.form)
    if not form.validation():
        return render_template('insert.html', form=form), 400
    return redirect('/')

这是html页面:

<form method="post" action="/insert">
      {{ form.csrf_token }}
      <div> {{form.name.label}}: {{form.name}}  </div>

        {% if form.name.errors %}
            <ul class=errors>
                {% for error in form.name.errors %}
                    <li>{{ error }}</li>
                {% endfor %}
            </ul>
        {% endif %}


      <div> {{form.nazionalita.label}}: {{form.nazionalita}} </div>

        {% if form.nazionalita.errors %}
            <ul class=errors>
                {% for error in form.nazionalita.errors %}
                    <li>{{ error }}</li>
                {% endfor %}
            </ul>
        {% endif %}

      <div> {{form.eta.label}}: {{form.eta}} </div>

        {% if form.eta.errors %}
            <ul class=errors>
                {% for error in form.eta.errors %}
                    <li>{{ error }}</li>
                {% endfor %}
            </ul>
        {% endif %}

      <div> {{form.Data.label}}: {{form.Data}} </div>

        {% if form.Data.errors %}
            <ul class=errors>
                {% for error in form.Data.errors %}
                    <li>{{ error }}</li>
                {% endfor %}
            </ul>
        {% endif %}

      <div> {{form.Comment.label}}: {{form.Comment}} </div>

        {% if form.Comment.errors %}
            <ul class=errors>
                {% for error in form.Comment.errors %}
                    <li>{{ error }}</li>
                {% endfor %}
            </ul>
        {% endif %}

      <div> {{form.submit}} </div>
    </form>

如果我删除selectField一切正常,但有了它,错误是:

    `Traceback (most recent call last):
     File "/home/roberto/Scrivania/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 267, in Handle
     result = handler(dict(self._environ), self._StartResponse)
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1994, in __call__
     return self.wsgi_app(environ, start_response)
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1985, in wsgi_app
     response = self.handle_exception(e)
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1540, in handle_exception
     reraise(exc_type, exc_value, tb)
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1982, in wsgi_app
     response = self.full_dispatch_request()
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1614, in full_dispatch_request
     rv = self.handle_user_exception(e)
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1517, in handle_user_exception
     reraise(exc_type, exc_value, tb)
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1612, in full_dispatch_request
     rv = self.dispatch_request()
     File "/home/roberto/Scrivania/simulazione/lib/flask/app.py", line 1598, in dispatch_request
     return self.view_functions[rule.endpoint](**req.view_args)
     File "/home/roberto/Scrivania/simulazione/app/handlers/insert.py",  line 46, in submit
     if not form.validate():
     File "/home/roberto/Scrivania/simulazione/lib/wtforms/form.py", line 310, in validate
     return super(Form, self).validate(extra)
     File "/home/roberto/Scrivania/simulazione/lib/wtforms/form.py", line 152, in validate
     if not field.validate(self, extra):
     File "/home/roberto/Scrivania/simulazione/lib/wtforms/fields/core.py", line 193, in validate
     self.pre_validate(form)
     File "/home/roberto/Scrivania/simulazione/lib/wtforms/fields/core.py", line 468, in pre_validate
     for v, _ in self.choices:
     TypeError: 'NoneType' object is not iterable`

我不明白为什么e如何解决这个问题 谢谢大家。

1 个答案:

答案 0 :(得分:1)

我终于能够重现您的错误:您正在视图函数中为GET方法创建选项。但是您没有将它们添加到POST方法的视图函数中。通过稍微修改submit()功能来解决此问题:

@app.route('/insert', methods=['POST'])
def submit():
    form = CommentForm(request.form)
    scelte = [( s['callingCodes'] , s['name'] )for s in nation]
    form.nazionalita.choices= scelte

    if not form.validate():
        return render_template('insert.html', form=form), 400
    return redirect('/')

这样您也可以在帖子功能中添加选项,然后您可以验证它们。更简洁的方法是将GET和POST处理程序放在同一个函数中:

注意:在原始版本中,form.validate()函数会尝试通过迭代form.nazionalita.choices列表来确定您是否做出了有效选择。由于您未在Form类中设置任何选项,因此它为None。并尝试迭代None会引发您的异常。