Flask Admin - 使用 on_model_change() 访问旧值
Flask Admin - Access old values using on_model_change()
我的目标是在用户更改现有记录的值时执行一些额外的操作。
我找到了on_model_change()in the docs,写了下面的代码:
def on_model_change(self, form, model, is_created):
# get old and new value
old_name = model.name
new_name = form.name
if new_name != old_name:
# if the value is changed perform some other action
rename_files(new_name)
我的期望是 model
参数将代表应用表单中的新值之前的记录。它没。相反,我发现 model
始终具有与 form
相同的值,这意味着 if 语句从未实现。
后来我试了这个:
class MyView(ModelView):
# excluding the name field from the form
form_excluded_columns = ('name')
form_extra_fields = {
# and adding a set_name field instead
'set_name':StringField('Name')
}
...
def on_model_change(self, form, model, is_created):
# getting the new value from set_name instead of name
new_name = form.set_name
...
虽然这解决了我的目标,但也带来了一个问题:
set_name
字段不会预先填充现有名称,即使用户不打算更改它也会强制用户键入名称
我还尝试在 on_model_change()
开始时执行 db.rollback()
这将撤消 flask-admin 所做的所有更改,并使 model
代表旧数据。这相当 hacky,导致我自己重新实现了很多 flask 管理代码,这变得很混乱。
解决这个问题的最佳方法是什么?
我是如何解决的
我使用 on_form_prefill 来预填充新名称字段而不是@pjcunningham 的答案。
# fill values from model
def on_form_prefill(self, form, id):
# get track model
track = Tracks.query.filter_by(id=id).first()
# fill new values
form.set_name.data = track.name
重写您认为的方法 update_model。如果您使用 SqlAlchemy 视图,这是默认行为,我添加了一些注释来解释模型的状态。
def update_model(self, form, model):
"""
Update model from form.
:param form:
Form instance
:param model:
Model instance
"""
try:
# at this point model variable has the unmodified values
form.populate_obj(model)
# at this point model variable has the form values
# your on_model_change is called
self._on_model_change(form, model, False)
# model is now being committed
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext('Failed to update record. %(error)s', error=str(ex)), 'error')
log.exception('Failed to update record.')
self.session.rollback()
return False
else:
# model is now committed to the database
self.after_model_change(form, model, False)
return True
你会想要像下面这样的东西,这取决于你把支票放在哪里,我已经在提交模型后放了它:
def update_model(self, form, model):
"""
Update model from form.
:param form:
Form instance
:param model:
Model instance
"""
try:
old_name = model.name
new_name = form.name.data
# continue processing the form
form.populate_obj(model)
self._on_model_change(form, model, False)
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext('Failed to update record. %(error)s', error=str(ex)), 'error')
log.exception('Failed to update record.')
self.session.rollback()
return False
else:
# the model got committed now run our check:
if new_name != old_name:
# if the value is changed perform some other action
rename_files(new_name)
self.after_model_change(form, model, False)
return True
您可以为 create_model and delete_model 覆盖类似的方法。
我的目标是在用户更改现有记录的值时执行一些额外的操作。
我找到了on_model_change()in the docs,写了下面的代码:
def on_model_change(self, form, model, is_created):
# get old and new value
old_name = model.name
new_name = form.name
if new_name != old_name:
# if the value is changed perform some other action
rename_files(new_name)
我的期望是 model
参数将代表应用表单中的新值之前的记录。它没。相反,我发现 model
始终具有与 form
相同的值,这意味着 if 语句从未实现。
后来我试了这个:
class MyView(ModelView):
# excluding the name field from the form
form_excluded_columns = ('name')
form_extra_fields = {
# and adding a set_name field instead
'set_name':StringField('Name')
}
...
def on_model_change(self, form, model, is_created):
# getting the new value from set_name instead of name
new_name = form.set_name
...
虽然这解决了我的目标,但也带来了一个问题:
set_name
字段不会预先填充现有名称,即使用户不打算更改它也会强制用户键入名称
我还尝试在 on_model_change()
开始时执行 db.rollback()
这将撤消 flask-admin 所做的所有更改,并使 model
代表旧数据。这相当 hacky,导致我自己重新实现了很多 flask 管理代码,这变得很混乱。
解决这个问题的最佳方法是什么?
我是如何解决的
我使用 on_form_prefill 来预填充新名称字段而不是@pjcunningham 的答案。
# fill values from model
def on_form_prefill(self, form, id):
# get track model
track = Tracks.query.filter_by(id=id).first()
# fill new values
form.set_name.data = track.name
重写您认为的方法 update_model。如果您使用 SqlAlchemy 视图,这是默认行为,我添加了一些注释来解释模型的状态。
def update_model(self, form, model):
"""
Update model from form.
:param form:
Form instance
:param model:
Model instance
"""
try:
# at this point model variable has the unmodified values
form.populate_obj(model)
# at this point model variable has the form values
# your on_model_change is called
self._on_model_change(form, model, False)
# model is now being committed
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext('Failed to update record. %(error)s', error=str(ex)), 'error')
log.exception('Failed to update record.')
self.session.rollback()
return False
else:
# model is now committed to the database
self.after_model_change(form, model, False)
return True
你会想要像下面这样的东西,这取决于你把支票放在哪里,我已经在提交模型后放了它:
def update_model(self, form, model):
"""
Update model from form.
:param form:
Form instance
:param model:
Model instance
"""
try:
old_name = model.name
new_name = form.name.data
# continue processing the form
form.populate_obj(model)
self._on_model_change(form, model, False)
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext('Failed to update record. %(error)s', error=str(ex)), 'error')
log.exception('Failed to update record.')
self.session.rollback()
return False
else:
# the model got committed now run our check:
if new_name != old_name:
# if the value is changed perform some other action
rename_files(new_name)
self.after_model_change(form, model, False)
return True
您可以为 create_model and delete_model 覆盖类似的方法。