【问题标题】:"form.populate_by returns" ERROR:'list' object has no attribute“form.populate_by 返回”错误:'list' 对象没有属性
【发布时间】:2019-03-30 22:23:10
【问题描述】:

我正在创建一个视图函数来使用 wtform 编辑数据库,我想用不同表单提供的数据库中保存的信息填充表单,我的问题是提供详细信息的查询

我已阅读手册https://wtforms.readthedocs.io/en/stable/crash_course.html 以及以下问题Python Flask-WTF - use same form template for add and edit operations 但我的查询似乎没有提供正确的数据格式

数据库模型:

class Sensors(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    sensorID = db.Column(db.String, unique=True)
    name = db.Column(db.String(30), unique=True)

表单模型:

class AddSensorForm(FlaskForm):
    sensorID = StringField('sensorID', validators=[DataRequired()])
    sensorName = StringField('sensorName', validators=[DataRequired()])
    submit = SubmitField('Register')

查看功能:

@bp.route('/sensors/editsensor/<int:id>', methods=('GET', 'POST'))
@login_required
def editsensor(id):
    edit = [(s.sensorID, s.sensorName) for s in db.session.\
      query(Sensors).filter_by(id=id).all()]
    form = AddSensorForm(obj=edit)
    form.populate_obj(edit)
    if form.validate_on_submit():
        sensors = Sensors(sensorID=form.sensorID.data, sensorName=form.sensorNa$
        db.session.add(sensors)
        db.session.commit()

查询的shell代码:

from homeHeating import db
from homeHeating import create_app
app = create_app()
app.app_context().push()
def editsensor(id):
    edit = [(s.sensorID, s.sensorName) for s in db.session.query(Sensors).filter_by(id=id).all()]
    print(edit)

editsensor(1)
[('28-0000045680fde', 'Boiler input')]

我希望这两个表单字段将填充有关由其“id”调用的传感器的信息 但我收到此错误

File "/home/pi/heating/homeHeating/sensors/sensors.py", line 60, in 
editsensor
form.populate_obj(edit)
File "/home/pi/heating/venv/lib/python3.7/site- 
packages/wtforms/form.py", line 96, in populate_obj
Open an interactive python shell in this 
framefield.populate_obj(obj, name)
File "/home/pi/heating/venv/lib/python3.7/site- 
packages/wtforms/fields/core.py", line 330, in populate_obj
setattr(obj, name, self.data)
AttributeError: 'list' object has no attribute 'sensorID'

错误表明它需要每个字段 2 个部分“framefield.populate_obj(obj, name) 我只提供了一个列数据而不是列名,“sensorID” 如果我将 # 行“edit = ...”散列,则没有错误消息并且返回表单但字段为空。所以我希望表单与数据库中的信息一起返回,填写以便我可以修改名称或传感器ID,然后更新数据库。

我希望这很清楚

热烈的问候

保罗。

ps 我已按照说明进行操作,因此 ERROR 语句只是“field.populate_by”之后的部分。

【问题讨论】:

    标签: flask flask-sqlalchemy flask-wtforms


    【解决方案1】:

    您正在尝试将 1 项列表传递给您的表单。

    通常,当您根据模型的主键选择单个记录时,使用 Query.get() 而不是 Query.filter(...).all()[0]。

    此外,您需要将请求数据传递给您的表单以在提交时对其进行验证,并在表单报告错误时预先填写字段。

    Form.validate_on_submit 只有在您的请求方法是 POST 并且您的表单通过验证时才会返回 True;这是您的表单告诉您“用户提供了语法正确的信息,现在您可以进行更多检查,我可以使用提供给我的数据填充现有对象”的步骤。

    您还需要处理第一次向用户显示表单的情况。

    @bp.route('/sensors/editsensor/<int:id>', methods=('GET', 'POST'))
    @login_required
    def editsensor(id):
        obj = Sensors.query.get(id) or Sensors()
        form = AddSensorForm(request.form, obj=obj)
    
        if form.validate_on_submit():
            form.populate_obj(obj)
            db.session.add(obj)
            db.session.commit()
    
            # return response or redirect here
            return redirect(...)
    
        else:
            # either the form has errors, or the user is displaying it for
            # the first time (GET)
    
            return render_template('sensors.html', form=form, obj=obj)
    

    【讨论】:

    • 您可以通过创建新的传感器实例来处理get(id) 不返回任何内容的情况,轻松将此“编辑传感器视图”更改为通用的“创建或编辑传感器视图”。 obj = Sensors.query.get(id) or Sensors()
    • 它工作!非常感谢您,非常感谢您查看我的问题。并帮助我!!!!!!
    • 非常欢迎您!如果这个答案有用,请投票和/或接受它作为答案。
    • 哦,忘了补充,Flask-SQLAlchemy 提供了一个 get_or_404(id) 方法,当找不到对象时会引发 404 异常,中止请求并显示 404 页面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 2018-09-28
    • 2022-11-25
    • 1970-01-01
    • 2016-08-19
    • 1970-01-01
    相关资源
    最近更新 更多