【发布时间】:2018-12-07 01:49:57
【问题描述】:
我有一个数据模型,它有一个依赖于其他列值的列,按照this 页面中的说明,我创建了一个上下文相关函数,用于在创建时确定此特定列的值,像这样:
def get_column_value_from_context(context):
# Instructions to produce value
return value
class MyModel(db.Model):
id = db.Column(db.Integer,
primary_key=True)
my_column = db.Column(db.String(64),
nullable=False,
default=get_column_value_from_context)
name = db.Column(db.String(32),
nullable=False,
unique=True,
index=True)
title = db.Column(db.String(128),
nullable=False)
description = db.Column(db.String(256),
nullable=False)
这种方法效果不错,我可以从命令行或使用脚本毫无问题地创建行。
我还使用 Flask-Admin 向应用添加了ModelView:
class MyModelView(ModelView):
can_view_details = True
can_set_page_size = True
can_export = True
admin.add_view(MyModelView(MyModel, db.session))
在我单击 list 视图中的 Create 按钮之前,这也很有效。我收到此错误:
AttributeError: 'NoneType' 对象没有属性 'get_current_parameters'
因为ModelView中的create_model处理程序的实现是this:
def create_model(self, form):
"""
Create model from form.
:param form:
Form instance
"""
try:
model = self.model()
form.populate_obj(model)
self.session.add(model)
self._on_model_change(form, model, True)
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext('Failed to create record. %(error)s', error=str(ex)), 'error')
log.exception('Failed to create record.')
self.session.rollback()
return False
else:
self.after_model_change(form, model, True)
return model
当模型被实例化时,这里没有context。因此,我创建了一个自定义视图,可以重新定义创建处理程序中的模型实例化:
class CustomSQLAView(ModelView):
def __init__(self, *args, **kwargs):
super(CustomSQLAView, self).__init__(*args, **kwargs)
def create_model(self, form):
"""
Create model from form.
:param form:
Form instance
"""
try:
model = self.get_populated_model(form)
self.session.add(model)
self._on_model_change(form, model, True)
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext('Failed to create record. %(error)s', error=str(ex)), 'error')
log.exception('Failed to create record.')
self.session.rollback()
return False
else:
self.after_model_change(form, model, True)
return model
def get_populated_model(self, form):
model = self.model()
form.populate_obj(model)
return model
现在我可以重新定义get_populated_model 方法来以通常的方式实例化模型:
class MyModelView(CustomSQLAView):
can_view_details = True
can_set_page_size = True
can_export = True
def get_populated_model(self, form):
model = self.model(
name=form.name.data,
title=form.title.data,
description=form.description.data,
)
return model
尽管这可行,但我怀疑它会破坏某些东西。 Flask-Admin 有多个表单和字段的populate_obj 方法的实现,所以我想保证一切安全。
这样做的正确方法是什么?
【问题讨论】:
-
在进入文档和代码之前,是否有理由不能修改模型的
__init__方法而不是使用上下文函数? -
很明显,有些列依赖于上下文,并且在使用
form.populate_obj方法填充模型之前,模型是在没有参数的情况下实例化的。 -
对于后来的旅行者,我已经在flask-admin上打开了一个问题:github.com/flask-admin/flask-admin/issues/2010
标签: python flask flask-sqlalchemy flask-admin