wtf-forms populate.object AttributeError: 'Heatingcircuit' object has no attribute 'translate' when editing db entry
wtf-forms populate.object AttributeError: 'Heatingcircuit' object has no attribute 'translate' when editing db entry
首先我知道问题是什么,但我不知道为什么或如何解决它,我知道该函数需要将字符串传递给数据库,我有一个用于创建和编辑的视图函数,在创建部分我已经添加 "str" 到功能来解决问题,但我不知道如何为编辑部分执行此操作。该表单有一个 querySelectField,它已为创建部分正确填充,当我提交 "str" 时,它会正确转换查询结果。
为了解决这个问题,我在函数的创建部分添加了 "str",但我看不出如何使用 'populate.obj' 将其添加到编辑部分,我也希望如此创建表单时要用数据库中存储的数据填充的字段,但事实并非如此。只是这个 QuerySelectfield 导致了问题。这是我的一些代码。
@bp.route('/control/addheatingcircuit', methods=['GET', 'POST'])
@bp.route('/control/addheatingcircuit/<int:id>', methods=('GET',
'POST'))
@login_required
def addheatingcircuit(id=None):
if id is not None:
obj = Heatingcircuit.query.get(id) or Heatingcircuit()
form = AddHeatingcircuitForm(request.form, obj=obj)
if form.validate_on_submit():
form.populate_obj(obj)
db.session.add(obj)
db.session.commit()
return redirect(url_for('index.index'))
else:
form = AddHeatingcircuitForm()
if form.validate_on_submit():
heatingcircuit = Heatingcircuit(name=form.name.data,
sensor_ID1=str(form.sensor_ID1.data),\ #here i have added 'str'
pin_ID1=str(form.pin_ID1.data))
db.session.add(heatingcircuit)
db.session.commit()
flash('Congratulations, you are now a registered a new
device!')
return redirect(url_for('index.index'))
return render_template('control/addheatingcircuit.html', title=
'add edit heating circuit',
form=form)
forms.py
from wtforms_alchemy.fields import QuerySelectField
class AddHeatingcircuitForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
sensor_ID1 = QuerySelectField('sensor_ID1',
query_factory=lambda: Sensors.query.all(),
allow_blank=True, get_label='sensorID')
sensor_ID2 = QuerySelectField('sensor_ID2',
query_factory=lambda: Sensors.query.all(),
allow_blank=True, get_label='sensorID')
.....
models.py
class Heatingcircuit(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
sensor_ID1 = db.Column(db.String(30))
sensor_ID2 = db.Column(db.String(30))
sensor_ID3 = db.Column(db.String(30))
pin_ID1 = db.Column(db.Integer)
pin_ID2 = db.Column(db.Integer)
pin_ID3 = db.Column(db.Integer)
temp = db.Column(db.Float)
state = db.Column(db.String(9))
timer = db.relationship('Timers', backref='time')
def __repr__(self):
return '{}'.format(self.id)
我在论坛上看了很多问题,但这是最接近的匹配项
所以正如所解释的那样,我希望编辑现有条目部分的功能用已经注册的信息填充表单,并且当我更改它并提交填充的表单时,我会收到此错误消息;
AttributeError: 'Heatingcircuit' object has no attribute 'translate'
(如果需要,可以提供完整的错误日志)
非常感谢保罗
编辑,我正在看教程 https://www.rithmschool.com/courses/flask-fundamentals/forms-with-wtforms
Here 它讨论了 CSRF 以及如何禁用令牌以遍历表单,我的问题可能是这个。
此问题也会影响 SelectField。
编辑2
我通过错误"sqlalchemy.exc.InvalidRequestError: Entity '' has no property 'enabled'"尝试了link http://wtforms.simplecodes.com/docs/0.6.1/ext.html#module-wtforms.ext.sqlalchemy.fields这段代码中提到的想法
这是我的代码
def enabled_sensors():
return Sensors.query.filter_by(enabled=True)
但这失败了
编辑错误
Traceback (most recent call last):
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
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)
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)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
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)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask_login/utils.py", line 261, in decorated_view
return func(*args, **kwargs)
File "/home/pi/heating/homeHeating/control/control.py", line 154, in addheatingcircuit
db.session.commit()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/scoping.py", line 162, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 1026, in commit
self.transaction.commit()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 493, in commit
self._prepare_impl()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 472, in _prepare_impl
self.session.flush()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 2451, in flush
self._flush(objects)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 2589, in _flush
transaction.rollback(_capture_exception=True)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 129, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 2549, in _flush
flush_context.execute()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 422, in execute
rec.execute(self)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 589, in execute
uow,
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 236, in save_obj
update,
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 978, in _emit_update_statements
statement, multiparams
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 988, in execute
return meth(self, multiparams, params)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1107, in _execute_clauseelement
distilled_params,
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1248, in _execute_context
e, statement, parameters, cursor, context
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1468, in _handle_dbapi_exception
util.reraise(*exc_info)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 129, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1244, in _execute_context
cursor, statement, parameters, context
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
cursor.execute(statement, parameters)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 168, in execute
query = self.mogrify(query, args)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 147, in mogrify
query = query % self._escape_args(args, conn)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 127, in _escape_args
return {key: conn.literal(val) for (key, val) in args.items()}
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 127, in <dictcomp>
return {key: conn.literal(val) for (key, val) in args.items()}
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/connections.py", line 467, in literal
return self.escape(obj, self.encoders)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/connections.py", line 460, in escape
return converters.escape_item(obj, self.charset, mapping=mapping)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/converters.py", line 27, in escape_item
val = encoder(val, mapping)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/converters.py", line 118, in escape_unicode
return u"'%s'" % _escape_unicode(value)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/converters.py", line 73, in _escape_unicode
return value.translate(_escape_table)
AttributeError: 'Sensors' object has no attribute 'translate'
我在 "def addpin():" 函数的后半部分收到了同样的错误消息,我研究发现我需要 return 一个字符串,所以我添加了 str(form.sensor_ID1.data)
"str" 这解决了那里的问题但是函数的前半部分是编辑部分,我现在在那里遇到了问题但不知道如何解决。
我相信错误就在这里;
if id is not None:
obj = Heatingcircuit.query.get(id) or Heatingcircuit()
form = AddHeatingcircuitForm(request.form, obj=obj)
if form.validate_on_submit():
form.populate_obj(obj)
db.session.add(obj)
db.session.commit()
感谢您的帮助
温暖的问候
保罗
两个问题。首先,QuerySelectField 的 query_factory
参数接受查询,而不是结果列表。所以去掉 .all()
:
sensor_ID1 = QuerySelectField('sensor_ID1',
query_factory=lambda: Sensors.query,
allow_blank=True, get_label='sensorID')
其次,给定表单字段的 data
将为您提供一个 Sensors
对象。所以你不能只投它,你需要向它询问它的id
。 pin_ID1
字段也是如此。如何执行此操作取决于 Sensors
class 的声明方式:
heatingcircuit = Heatingcircuit(
name=form.name.data,
sensor_ID1=form.sensor_ID1.data.sensorID,
pin_ID1=form.pin_ID1.data.pinID
)
首先我知道问题是什么,但我不知道为什么或如何解决它,我知道该函数需要将字符串传递给数据库,我有一个用于创建和编辑的视图函数,在创建部分我已经添加 "str" 到功能来解决问题,但我不知道如何为编辑部分执行此操作。该表单有一个 querySelectField,它已为创建部分正确填充,当我提交 "str" 时,它会正确转换查询结果。
为了解决这个问题,我在函数的创建部分添加了 "str",但我看不出如何使用 'populate.obj' 将其添加到编辑部分,我也希望如此创建表单时要用数据库中存储的数据填充的字段,但事实并非如此。只是这个 QuerySelectfield 导致了问题。这是我的一些代码。
@bp.route('/control/addheatingcircuit', methods=['GET', 'POST'])
@bp.route('/control/addheatingcircuit/<int:id>', methods=('GET',
'POST'))
@login_required
def addheatingcircuit(id=None):
if id is not None:
obj = Heatingcircuit.query.get(id) or Heatingcircuit()
form = AddHeatingcircuitForm(request.form, obj=obj)
if form.validate_on_submit():
form.populate_obj(obj)
db.session.add(obj)
db.session.commit()
return redirect(url_for('index.index'))
else:
form = AddHeatingcircuitForm()
if form.validate_on_submit():
heatingcircuit = Heatingcircuit(name=form.name.data,
sensor_ID1=str(form.sensor_ID1.data),\ #here i have added 'str'
pin_ID1=str(form.pin_ID1.data))
db.session.add(heatingcircuit)
db.session.commit()
flash('Congratulations, you are now a registered a new
device!')
return redirect(url_for('index.index'))
return render_template('control/addheatingcircuit.html', title=
'add edit heating circuit',
form=form)
forms.py
from wtforms_alchemy.fields import QuerySelectField
class AddHeatingcircuitForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
sensor_ID1 = QuerySelectField('sensor_ID1',
query_factory=lambda: Sensors.query.all(),
allow_blank=True, get_label='sensorID')
sensor_ID2 = QuerySelectField('sensor_ID2',
query_factory=lambda: Sensors.query.all(),
allow_blank=True, get_label='sensorID')
.....
models.py
class Heatingcircuit(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
sensor_ID1 = db.Column(db.String(30))
sensor_ID2 = db.Column(db.String(30))
sensor_ID3 = db.Column(db.String(30))
pin_ID1 = db.Column(db.Integer)
pin_ID2 = db.Column(db.Integer)
pin_ID3 = db.Column(db.Integer)
temp = db.Column(db.Float)
state = db.Column(db.String(9))
timer = db.relationship('Timers', backref='time')
def __repr__(self):
return '{}'.format(self.id)
我在论坛上看了很多问题,但这是最接近的匹配项
所以正如所解释的那样,我希望编辑现有条目部分的功能用已经注册的信息填充表单,并且当我更改它并提交填充的表单时,我会收到此错误消息;
AttributeError: 'Heatingcircuit' object has no attribute 'translate'
(如果需要,可以提供完整的错误日志)
非常感谢保罗
编辑,我正在看教程 https://www.rithmschool.com/courses/flask-fundamentals/forms-with-wtforms Here 它讨论了 CSRF 以及如何禁用令牌以遍历表单,我的问题可能是这个。 此问题也会影响 SelectField。
编辑2 我通过错误"sqlalchemy.exc.InvalidRequestError: Entity '' has no property 'enabled'"尝试了link http://wtforms.simplecodes.com/docs/0.6.1/ext.html#module-wtforms.ext.sqlalchemy.fields这段代码中提到的想法 这是我的代码
def enabled_sensors():
return Sensors.query.filter_by(enabled=True)
但这失败了 编辑错误
Traceback (most recent call last):
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
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)
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)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
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)
File "/home/pi/heating/venv/lib/python3.7/site-packages/flask_login/utils.py", line 261, in decorated_view
return func(*args, **kwargs)
File "/home/pi/heating/homeHeating/control/control.py", line 154, in addheatingcircuit
db.session.commit()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/scoping.py", line 162, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 1026, in commit
self.transaction.commit()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 493, in commit
self._prepare_impl()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 472, in _prepare_impl
self.session.flush()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 2451, in flush
self._flush(objects)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 2589, in _flush
transaction.rollback(_capture_exception=True)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 129, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/session.py", line 2549, in _flush
flush_context.execute()
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 422, in execute
rec.execute(self)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/unitofwork.py", line 589, in execute
uow,
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 236, in save_obj
update,
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/orm/persistence.py", line 978, in _emit_update_statements
statement, multiparams
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 988, in execute
return meth(self, multiparams, params)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1107, in _execute_clauseelement
distilled_params,
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1248, in _execute_context
e, statement, parameters, cursor, context
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1468, in _handle_dbapi_exception
util.reraise(*exc_info)
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 129, in reraise
raise value
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1244, in _execute_context
cursor, statement, parameters, context
File "/home/pi/heating/venv/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
cursor.execute(statement, parameters)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 168, in execute
query = self.mogrify(query, args)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 147, in mogrify
query = query % self._escape_args(args, conn)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 127, in _escape_args
return {key: conn.literal(val) for (key, val) in args.items()}
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/cursors.py", line 127, in <dictcomp>
return {key: conn.literal(val) for (key, val) in args.items()}
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/connections.py", line 467, in literal
return self.escape(obj, self.encoders)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/connections.py", line 460, in escape
return converters.escape_item(obj, self.charset, mapping=mapping)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/converters.py", line 27, in escape_item
val = encoder(val, mapping)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/converters.py", line 118, in escape_unicode
return u"'%s'" % _escape_unicode(value)
File "/home/pi/heating/venv/lib/python3.7/site-packages/pymysql/converters.py", line 73, in _escape_unicode
return value.translate(_escape_table)
AttributeError: 'Sensors' object has no attribute 'translate'
我在 "def addpin():" 函数的后半部分收到了同样的错误消息,我研究发现我需要 return 一个字符串,所以我添加了 str(form.sensor_ID1.data)
"str" 这解决了那里的问题但是函数的前半部分是编辑部分,我现在在那里遇到了问题但不知道如何解决。
我相信错误就在这里;
if id is not None:
obj = Heatingcircuit.query.get(id) or Heatingcircuit()
form = AddHeatingcircuitForm(request.form, obj=obj)
if form.validate_on_submit():
form.populate_obj(obj)
db.session.add(obj)
db.session.commit()
感谢您的帮助 温暖的问候 保罗
两个问题。首先,QuerySelectField 的 query_factory
参数接受查询,而不是结果列表。所以去掉 .all()
:
sensor_ID1 = QuerySelectField('sensor_ID1',
query_factory=lambda: Sensors.query,
allow_blank=True, get_label='sensorID')
其次,给定表单字段的 data
将为您提供一个 Sensors
对象。所以你不能只投它,你需要向它询问它的id
。 pin_ID1
字段也是如此。如何执行此操作取决于 Sensors
class 的声明方式:
heatingcircuit = Heatingcircuit(
name=form.name.data,
sensor_ID1=form.sensor_ID1.data.sensorID,
pin_ID1=form.pin_ID1.data.pinID
)