У меня есть модель данных, у которой есть столбец, который зависит от других значений столбца, следуя инструкциям на этой странице. Я создал контекстно-зависимую функцию, которая используется для определения значения этого конкретного колонка о создании, примерно так:
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)
Этот подход работает довольно прилично, я могу без проблем создавать строки из командной строки или используя скрипт.
Я также добавил ModelView
в приложение, используя Flask-Admin:
class MyModelView(ModelView):
can_view_details = True
can_set_page_size = True
can_export = True
admin.add_view(MyModelView(MyModel, db.session))
Это также работает довольно прилично, пока я не нажму кнопку Создать в представлении список . Я получаю эту ошибку:
AttributeError: у объекта 'NoneType' нет атрибута 'get_current_parameters'
Поскольку реализация обработчика create_model
в ModelView
равна , это :
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
метода форм и полей, поэтому я хотел бы сохранить все в безопасности.
Как правильно это сделать?