Python 类型错误:';非类型';对象不可用于字段选择

Python 类型错误:';非类型';对象不可用于字段选择,python,flask-wtforms,Python,Flask Wtforms,下面的代码返回“TypeError”,我认为引起问题的代码部分是 “available_boilers=db.session.query(boilers.name).all()boiler_list=[(b.name)用于可用_boilers中的b]” 其中,应迭代锅炉列表以形成表单中的下拉列表。我使用Flask Bootstrap quick form来显示列表,所以我认为我的问题不在这里,为了检查列表是否正在发送,我检查了shell中的部分代码 @bp.route('/control/add

下面的代码返回“TypeError”,我认为引起问题的代码部分是 “available_boilers=db.session.query(boilers.name).all()boiler_list=[(b.name)用于可用_boilers中的b]” 其中,应迭代锅炉列表以形成表单中的下拉列表。我使用Flask Bootstrap quick form来显示列表,所以我认为我的问题不在这里,为了检查列表是否正在发送,我检查了shell中的部分代码

@bp.route('/control/addboiler_circuit', methods=('GET', 'POST'))
def addboiler_circuit():
    available_boilers = db.session.query(Boilers.name).all()
    boiler_list = [(b.name) for b in available_boilers]
    form = AddBoiler_CircuitForm()
    form.name.choices = boiler_list
    if form.validate_on_submit():
        boiler_circuits = Boilers_Circuit(name=form.name.data,\
                          BoilerName=form.BoilerName.data)
        db.session.add(boilers_circuits)
        db.session.commit()
        flash('Congratulations, you have now a registered a new boiler 
      circuit!')
        return redirect(url_for('control.addboiler_circuit'))
    return render_template('control/addboiler_circuit.html', title='Add boiler',
                       form=form)
form.py

class AddBoiler_CircuitForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
BoilerName = SelectField('BoilerName', coerce=int, validators=[DataRequired()])

def validate_boilerName(self, boilerName):
    boilers = Boilers_Circuit.query.filter_by(boiler=BoilerName.data).first()
    if boilers is not None:
        raise ValidationError('Please use a different Boiler.')
蟒蛇壳

>>> available_boilers = db.session.query(Boilers.name).all()
>>> print(available_boilers)
[('Log Burner',), ('solar panel',), ('pellet boiler',)]
>>> boiler_list = [(b.name) for b in available_boilers]
>>> print(boiler_list)
['Log Burner', 'solar panel', 'pellet boiler']
我的代码来自和来自

这是我的新领域,我需要帮助

编辑 这是完整的错误消息

> Traceback (most recent call last):
1/File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", 
line 2309, in __call__
return self.wsgi_app(environ, start_response)
2/ File "/home/pi/heating/venv/lib/python3.7/site- 
packages/flask/app.py", 
line 2295, in wsgi_app
response = self.handle_exception(e)
3/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
4/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
5/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
6/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
7/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
8/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
9/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
10/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
11/ File "/home/pi/heating/homeHeating/control/control.py", line 49, in addboiler_circuit
form=form)
12/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/templating.py", line 135, in render_template
context, ctx.app)
13/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/templating.py", line 117, in _render
rv = template.render(context)
14/ File "/home/pi/heating/venv/lib/python3.7/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
15/ File "/home/pi/heating/venv/lib/python3.7/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
16/ File "/home/pi/heating/venv/lib/python3.7/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
17/ File "/home/pi/heating/venv/lib/python3.7/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
18/ File "/home/pi/heating/homeHeating/templates/control/addboiler_circuit.html", line 2, in top-level template code
{% import 'bootstrap/wtf.html' as wtf %}
19/ File "/home/pi/heating/homeHeating/templates/base.html", line 1, 
 in top-level template code  {% extends 'bootstrap/base.html' %}
20/ File "/home/pi/heating/venv/lib/python3.7/site- 
  packages/flask_bootstrap/templates/bootstrap/base.html", line 1, in 
top-level template code
{% block doc -%}
21/ File "/home/pi/heating/venv/lib/python3.7/site- 
packages/flask_bootstrap/templates/bootstrap/base.html", line 4, in 
 block "doc"
{%- block html %}
21/ File "/home/pi/heating/venv/lib/python3.7/site- 
packages/flask_bootstrap/templates/bootstrap/base.html", line 20, in 
block 
"html"
 {% block body -%}
22/ File "/home/pi/heating/venv/lib/python3.7/site- 
packages/flask_bootstrap/templates/bootstrap/base.html", line 23, in 
block "body"
{% block content -%} 23/File"/home/pi/heating/homeHeating/templates/control/addboiler_circuit.html", line 8, in block "content" {{ wtf.quick_form(form) }}
24/ File "/home/pi/heating/venv/lib/python3.7/site-packages/jinja2/runtime.py", line 579, in _invoke rv = self._func(*arguments)
25/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask_bootstrap/templates/bootstrap/wtf.html", line 205, in template {{ form_field(field,
26/ File "/home/pi/heating/venv/lib/python3.7/site-packages/jinja2/runtime.py", line 579, in _invoke rv = self._func(*arguments)
27/ File "/home/pi/heating/venv/lib/python3.7/site-packages/flask_bootstrap/templates/bootstrap/wtf.html", line 123, in template {{field(class="form-control", **kwargs)|safe}}
28/ File "/home/pi/heating/venv/lib/python3.7/site packages/wtforms/fields/core.py", line 155, in __call__ return self.meta.render_field(self, kwargs)
29/ File "/home/pi/heating/venv/lib/python3.7/site packages/wtforms/meta.py", line 56, in render_field return field.widget(field, **render_kw)
30/ File "/home/pi/heating/venv/lib/python3.7/site packages/wtforms/widgets/core.py", line 323, in __call__ for val, label, selected in field.iter_choices():
31/ File "/home/pi/heating/venv/lib/python3.7/site packages/wtforms/fields/core.py", line 454, in iter_choices for value, label in self.choices:
TypeError: 'NoneType' object is not iterable
这是完整的错误脚本,第23行提到我的表单“addboiler_circuit.html”,我在下面添加了该表单:

{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}

{% block content %}
    <h1>{{ 'Register' }}</h1>
    <div class="row">
        <div class="col-md-4">
            {{ wtf.quick_form(form) }}
        </div>
    </div>
{% endblock %}
现在@sleblanc已经想出了一种全新的方法来编写这个函数,但是我该如何将其付诸实施呢?我有很多问题,我不知道从哪里开始。谢谢你的帮助

31/ File "/home/pi/heating/venv/lib/python3.7/site packages/wtforms/fields/core.py", line 454, in iter_choices for value, label in self.choices:
TypeError: 'NoneType' object is not iterable
这表明您的表单没有为boilerName字段设置选项。在您的代码中,似乎您正在这样做,但仔细检查后,您将在
name
字段而不是
boilerName
字段上设置选项

您的代码也存在其他问题<代码>选项应该是
(id,'label')
元组的列表。如果您的模型引用了一个文本字符串,那么您只需在可用的\u文件中为b执行
[(b.name,b.name)]

此外,由于您使用的是flask_wtf,因此应以这种方式重写视图,以使其更清晰:

@bp.route('/control/addboiler_circuit', methods=('GET', 'POST'))
def addboiler_circuit():
    available_boilers = Boilers.query.all()
    boiler_list = [(b.name) for b in available_boilers]

    obj = Circuit() # you may pass default parameters to this constructor
    form = AddBoiler_CircuitForm(request.form, obj=obj)
    form.name.choices = boiler_list

    if form.validate_on_submit():
        form.populate(obj)
        db.session.add(obj)
        db.session.commit()

        flash('Congratulations, you have now a registered a new '
              'boiler circuit!')

        return redirect(url_for('control.addboiler_circuit'))

    return render_template('control/addboiler_circuit.html', title='Add boiler',
                   form=form)

此外,考虑使用WTFraseSqLalCyy的QueRealStdFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldFieldField

from wtforms_sqlalchemy.fields import QuerySelectField

class AddBoiler_CircuitForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    boiler = QuerySelectField(
                'Boiler name', 
                query_factory=lambda: Boiler.query.all(),
                validators=[DataRequired()])

通过在您的电路模型上设置一个名为“boiler”的关系,表单的populate_obj将完全执行您期望它执行的操作。QuerySelectField甚至可以确保用户的选择包含在您提供的查询中,从而防止狡猾的用户编辑HTML表单和提交不允许的值。

谢谢@sleblanc,就在我认为我已经理解我在做什么的时候,你过来把它颠倒过来了,>然后你可以简单地做[(b.名称,b.名称)用于可用的锅炉中的b].我已经这样做了,但我现在可以看到,我从不同的教程中学到的每一件事可能都不正确,你上面写的内容更清楚,但我认为我以前在任何地方都没有见过。我将把它放在我的代码中,让你知道会发生什么。这很遗憾,但这个空间不适合用来对一些陌生人说谢谢我花了时间帮助另一个陌生人Losshi@sleblanc,我一直在看你的建议,并尝试了一下,我已将视图功能更改为匹配,并将两者组合起来填充字段,但使用此<1>而不是“1”,因此当我提交时,我会得到一个“翻译”错误。我已经看过wtforms alchemy网站,非常喜欢它的外观,因为我有几个关于设置的问题,我应该问一个新问题?再次感谢你的帮助。当然,发帖吧!一个新问题似乎很合适。我不确定“翻译”是什么错误可能意味着。查看它,AttributeError,某些东西没有属性“translate”可能意味着表单的某个部分在操作对象时需要一个普通字符串。嗨@sleblanc,在我发布新问题之前,你说过我可以使用相同的视图函数进行添加和编辑,但我不知道如何操作。你能给我举个例子吗?>qoute:你可以很容易地更改这个通过处理get(id)不返回任何内容的情况,通过创建传感器的新实例,将“编辑传感器视图”更改为通用的“创建或编辑传感器视图”。obj=Sensors.query.get(id)或Sensors()/qoute我不明白这一点!抱歉
from wtforms_sqlalchemy.fields import QuerySelectField

class AddBoiler_CircuitForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    boiler = QuerySelectField(
                'Boiler name', 
                query_factory=lambda: Boiler.query.all(),
                validators=[DataRequired()])