这是关于 Flask-appbuilder 的一个非常具体的问题。在我的开发过程中,我发现 FAB 的 ModelView 适合管理员角色,但需要更多的用户逻辑处理程序/视图来进行复杂的设计。
设备和用户之间存在多对多的关系,因为每个设备可以在多个用户之间共享,每个用户可以拥有多个设备。于是就有了一张叫做accesses的二级表,描述了设备和用户之间的访问控制。在此表中,如果用户拥有该设备,我将添加“isHost”。因此,我们有两个角色:主机和(普通)用户。但是,这些角色不是定义为其他应用程序的两个角色,因为一个人可以同时是主机或用户。在一个非常简单的应用程序中,强制用户切换两个角色不是很方便。这让事情变得更糟。
无论如何,我需要使用传统的 Flask/Jinja2 模板设计一些自定义处理程序。例如:
class PageView(ModelView):
# FAB default URL: "/pageview/list"
datamodel = SQLAInterface(Page)
list_columns = ['name', 'date', 'get_url']
@expose("/p/<string:url>")
def p(self, url):
title = urllib.unquote(url)
r = db.session.query(Page).filter_by(name = title).first()
if r:
md = r.markdown
parser = mistune.Markdown()
body = parser(md)
return self.render_template('page.html', title = title, body = body)
else:
return self.render_template('404.html'), 404
上面的降价页面 URL 很简单,因为它是一个单独的 UI。但是如果我去 DeviceView/AccountView/AccessView 进行列表/显示/添加/编辑操作。我意识到我需要一个独特风格的 UI。
那么,现在如何通过自定义 sqlalchemy 查询重用 FAB 的现有模板/小部件?这是我的 DeviceView 代码。
class DeviceView(ModelView):
datamodel = SQLAInterface(Device)
related_views = [EventView, AccessView]
show_template = 'appbuilder/general/model/show_cascade.html'
edit_template = 'appbuilder/general/model/edit_cascade.html'
@expose('/host')
@has_access
def host(self):
base_filters = [['name', FilterStartsWith, 'S'],]
#if there is not return, FAB will throw error
return "host view:{}".format(repr(base_filters))
@expose('/my')
@has_access
def my(self):
# A pure testing method
rec = db.session.query(Access).filter_by(id = 1).all()
if rec:
for r in rec:
print "rec, acc:{}, dev:{}, host:{}".format(r.account_id, r.device_id, r.is_host)
return self.render_template('list.html', title = "My Accesses", body = "{}".format(repr(r)))
else:
return repr(None)
除了带有 render_template() 的 sqlalchemy 代码,我猜 base_filters 还可以帮助定义自定义查询,但是,我不知道如何获取查询结果并渲染它们。
如果可能,请给我一些参考代码或示例。实际上,我在 FAB 的 github 资源中有 grep 关键字“db.session/render_template/expoaw”。但没有运气。