增长model后端
Flask-Admin对与之配合的数据库模型作了一些假设。 若是要实现本身的数据库后端,而且Flask-Admin的模型视图仍可按预期工做,则应注意如下事项:
1) 每个model必须有主键,但不限定数据类型和主键名
2) 确保每个model的属性都是能够访问的数据库
在此基础上,你能够经过继承BaseMiodelView类来实现数据库后端的扩展,并实现下面列出的一系列方法:
1 扩展BaseModelView
首先定义一个从BaseModelView派生的新类:后端
class MyDbModel(BaseModelView): pass
这个类继承了BaseModelView的__init__方法,它接受一个模型类做为第一个参数。 模型类存储为属性self.model,以便其余方法能够访问它。缓存
如今,为新的类实现如下脚手架方法:
1.1 get_pk_value()
该方法从模型实例中返回一个主键值。 在SQLAlchemy后端,它使用scaffold_pk()从模型得到主键,缓存它,而后在须要时从模型返回值。
例子:app
class MyDbModel(BaseModelView): def get_pk_value(self, model): return self.model.id
1.2 scaffold_list_columns()
返回列表视图要展现的列。例子:spa
class MyDbModel(BaseModelView): def scaffold_list_columns(self): columns = [] for p in dir(self.model): attr = getattr(self.model, p) if isinstance(attr, MyDbColumn): columns.append(p) return columns
1.3 scaffold_sortable_columns()
返回可排序列的字典。 字典中的键应该对应于模型的字段名称。 值应该是那些将用于排序的变量。code
例如,在SQLAlchemy后端能够按外键字段进行排序。 因此,若是有一个名为user的字段,它是Users表的一个外键,而且Users表也有一个名称字段,那么这个键将是user的value将是:Users.name。orm
若是您的后端不支持排序,则返回None或空字典。对象
1.4 init_search()
初始化搜索功能。 若是您的后端支持全文搜索,请进行初始化并返回True。 若是您的后端不支持全文搜索,请返回False。blog
例如,SQLAlchemy后端读取self.searchable_columns的值,并验证是否全部字段都是文本类型,若是它们定位到当前的模型(若是不是,则会添加一个链接等)并缓存这些信息以备未来使用。
1.5 scaffold_form()
在模型里定义WTForms表单,例子:排序
class MyDbModel(BaseModelView): def scaffold_form(self): class MyForm(Form): pass # Do something return MyForm
1.6 get_list()
这个方法应该返回带有分页,排序等应用的模型实例列表。
对于SQLAlchemy后端,它看起来像:
1)若是搜索已启用且提供的搜索值不为空,将会为self.searchable_columns中的每一个字段生成LIKE语句
2)若是传递过滤值,请使用值调用apply方法:
for flt, value in filters: query = self._filters[flt].apply(query, value)
3)执行查询获取数据库中的总行数(count)
4)若是sort_column被传递,会作相似的事情(带有一些额外的FK逻辑,在这个例子中省略):
if sort_desc: query = query.order_by(desc(sort_field)) else: query = query.order_by(sort_field)
5)应用分页
6)返回总条数和列表的元组
1.7 get_one()
根据主键返回model数据
1.8 create_model()
经过表单建立一个model的实例
1.9 update_model()
更新表单model的实例
1.10 delete_model()
从数据存储中删除特定的model数据
1.11 is_valid_filter()
验证返回的数据是不是有效的
1.12scaffold_filters()
返回一个模型字段的过滤器对象列表。
对于self.column_filters设置中的每一个条目,该方法都会被调用一次。
若是后端不知道如何为提供的字段生成过滤器,则应该返回None。
例如:
class MyDbModel(BaseModelView): def scaffold_filters(self, name): attr = getattr(self.model, name) if isinstance(attr, MyDbTextField): return [MyEqualFilter(name, name)]
2,实现过滤
每一个模型后端都应该有本身的一组过滤器实现。 在非SQLAlchemy后端不能使用SQLAlchemy模型中的过滤器。 这也意味着不一样的后端可能有不一样的可用过滤器集合。
过滤器是从BaseFilter派生的类,它实现了至少两种方法:
1. apply()
2. operation()
apply方法接受两个参数:查询对象和来自客户端的值。 在这里您能够为过滤器类型添加过滤逻辑。
让咱们以SQLAlchemy模型后端为例:
全部SQLAlchemy过滤器都从BaseSQLAFilter类派生。
每一个过滤器都实现一个简单的过滤器SQL操做(如,not like,大于等),并接受一列做为输入参数。每当模型视图要将筛选器应用于查询对象时,它将在具备查询和值的筛选器类中调用apply方法。 过滤器将应用实际的过滤器操做。
class MyBaseFilter(BaseFilter): def __init__(self, column, name, options=None, data_type=None): super(MyBaseFilter, self).__init__(name, options, data_type) self.column = column class MyEqualFilter(MyBaseFilter): def apply(self, query, value): return query.filter(self.column == value) def operation(self): return gettext('equals') # You can validate values. If value is not valid, # return `False`, so filter will be ignored. def validate(self, value): return True # You can "clean" values before they will be # passed to the your data access layer def clean(self, value): return value
若是您在添加新模型后端时遇到问题,请随时提问。 此外,若是遇到困难,请尝试查看SQLAlchemy模型后端并将其用做参考。