安装flask-admin
代码语言:javascript复制pip install flask-admin
初始化
代码语言:javascript复制from flask import Flask
from flask_admin import Admin
app = Flask(__name__)
# set optional bootswatch theme
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
admin = Admin(app, name='microblog', template_mode='bootstrap3')
# Add administrative views here
app.run()
这里,名称和模板模式参数都是可选的。或者,您可以使用init_app()方法。
如果启动此应用程序并导航到http://localhost:5000/admin/,则应该会看到一个顶部带有导航栏的空白页。通过指定适合您需要的引导样本主题自定义外观(有关可用样本,请参阅http://bootswatch.com/3/)。
添加模型视图(Adding Model Views)
模型视图允许您添加一组专用的管理页面,用于管理数据库中的任何模型。通过创建ModelView类的实例来实现这一点,您可以从Flask管理员的一个内置ORM后端导入该类。例如,sqlAlchemy后端,您可以使用如下所示:
代码语言:javascript复制from flask_admin.contrib.sqla import ModelView
# Flask and Flask-SQLAlchemy initialization here
admin = Admin(app, name='microblog', template_mode='bootstrap3')
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(Post, db.session))
这将为您的模型提供一组功能齐全的CRUD视图: 列表视图,支持搜索、排序、筛选和删除记录。 用于添加新记录的创建视图。 用于更新现有记录的编辑视图。 可选的只读详细信息视图。 有许多选项可用于自定义这些内置视图的显示和功能。有关详细信息,请参见自定义内置视图。有关其他可用ORM后端的详细信息,请参阅使用不同的数据库后端。
向索引页添加内容(Adding Content to the Index Page)
您访问http://localhost:5000/admin/时,您首先会注意到它只是一个带有导航菜单的空页面。若要向此页面添加一些内容,请将以下文本另存为项目模板目录中的admin/index.html:
代码语言:javascript复制{% extends 'admin/master.html' %}
{% block body %}
<p>Hello world</p>
{% endblock %}
这将覆盖默认索引模板,但仍会提供内置导航菜单。因此,现在您可以向索引页添加任何内容,同时保持一致的用户体验。
授权和权限(Authorization & Permissions)
为应用程序设置管理界面时,首先要解决的问题之一是如何避免不需要的用户进入。对于flask admin,有几种不同的方法来处理这个问题。
HTTP Basic Auth
幸的是,没有简单的方法可以将HTTP基本身份验证仅应用于管理界面。
最简单的身份验证形式是HTTP基本身份验证。它不会干扰数据库模型,也不需要编写任何新的视图逻辑或模板代码。所以当你在部署一些仍在开发中的东西时,在你希望全世界都能看到它之前,它是非常好的。
看看Flask-BasicAuth,看看将整个应用程序置于HTTP Basic Auth之后有多容易。
自定义(Rolling Your Own)
一个更为灵活的解决方案,Flask-Admin 让你可以在你的每个View类里面,通过简单的重写is_accessible方法定义访问控制规则。你如何实现逻辑取决于你自己,但如果你是使用像Flask-Admin一样低级别的包,那么限制登录可以简单地如:
代码语言:javascript复制class MicroBlogModelView(sqla.ModelView):
def is_accessible(self):
return login.current_user.is_authenticated
def inaccessible_callback(self, name, **kwargs):
# redirect to login page if user doesn't have access
return redirect(url_for('login', next=request.url))
在导航菜单中,特定用户无法访问的组件将不会显示给该用户。有关使用flask login和flask admin的示例,请查看https://github.com/flask-admin/flask-admin/tree/master/examples/auth-flask-login。
主要的缺点是,您仍然需要实现所有相关的登录、注册和帐户管理视图。
使用 Flask-Security(Using Flask-Security)
如果你想要一个更完美的解决方案,你可以使用 Flask-Security,这是一个更高级的库。它带有许多内置视图,用于执行诸如用户注册、登录、电子邮件地址确认、密码重置等常见操作。 唯一复杂的一点是使内置的flask安全视图与flask管理模板顺利集成,以创建一致的用户体验。要做到这一点,您需要重写内置的flask安全模板,并让它们通过在每个文件的顶部添加以下内容来扩展flask管理基模板:
{% extends 'admin/master.html' %}
现在,您需要手动传递一些上下文变量,以便在从Flask安全视图调用Flask管理模板时能够正确呈现这些模板。定义安全上下文处理器函数将为您解决此问题:
代码语言:javascript复制def security_context_processor():
return dict(
admin_base_template=admin.base_template,
admin_view=admin.index_view,
h=admin_helpers,
)
有关在flask admin中使用flask security的工作示例,请查看https://github.com/flask-admin/flask-admin/tree/master/examples/auth。
该示例只使用内置的注册和登录视图,但您可以使用相同的方法来包括其他视图,如忘记密码、发送确认等。
自定义内置视图(Customizing Built-in Views)
从ModelView继承时,可以为许多配置参数指定值。使用这些自定义视图以适合您的特定模型:
代码语言:javascript复制from flask_admin.contrib.sqla import ModelView
# Flask and Flask-SQLAlchemy initialization here
class MicroBlogModelView(ModelView):
can_delete = False # disable model deletion
page_size = 50 # the number of entries to display on the list view
admin.add_view(MicroBlogModelView(User, db.session))
admin.add_view(MicroBlogModelView(Post, db.session))
或者,同样地,您可以一次为单个模型指定选项:
代码语言:javascript复制class UserView(ModelView):
can_delete = False # disable model deletion
class PostView(ModelView):
page_size = 50 # the number of entries to display on the list view
admin.add_view(UserView(User, db.session))
admin.add_view(PostView(Post, db.session))
模型视图配置属性(ModelView Configuration Attributes)
有关定义的属性的完整列表,请查看BaseModelView()的API文档。以下是一些最常用的属性: 要禁用某些CRUD操作,请设置以下任一布尔参数:
can_create = False can_edit = False can_delete = False
如果模型中的数据太多,无法在列表视图中显示,则可以通过设置以下内容添加只读详细信息视图:
can_view_details = True
从列表视图中删除列很容易,只需为列传递列名称列表“不包括”列表参数:
column_exclude_list = ['password', ]
使列可搜索或用于筛选,请指定列名称列表:
column_searchable_list = ['name', 'email'] column_filters = ['country']
要获得更快的编辑体验,请在列表视图中启用内嵌编辑:
column_editable_list = ['name', 'last_name']
或者,让添加和编辑表单显示在列表页的模式窗口中,而不是专用的创建和编辑页面:
create_modal = True edit_modal = True
通过指定选择选项列表,可以限制文本字段的可能值:
代码语言:javascript复制form_choices = {
'title': [
('MR', 'Mr'),
('MRS', 'Mrs'),
('MS', 'Ms'),
('DR', 'Dr'),
('PROF', 'Prof.')
]
}
要从创建和编辑表单中删除字段,请执行以下操作:
代码语言:javascript复制form_excluded_columns = ['last_name', 'email']
指定WTForms字段参数:
代码语言:javascript复制form_args = {
'name': {
'label': 'First Name',
'validators': [required()]
}
}
或者,指定用于呈现这些字段的WTForms小部件的参数:
代码语言:javascript复制form_widget_args = {
'description': {
'rows': 10,
'style': 'color: black'
}
}
当表单包含外键时,通过Ajax加载这些相关模型,使用:
form_ajax_refs = {
'user': {
'fields': ['first_name', 'last_name', 'email'],
'page_size': 10
}
}
要筛选通过Ajax加载的结果,可以使用:
代码语言:javascript复制form_ajax_refs = {
'active_user': QueryAjaxModelLoader('user', db.session, User,
filters=["is_active=True", "id>1000"])
}
要在线管理相关模型:
inline_models = ['post', ]
可以自定义这些内联表单。请查看inline_models()的API文档。
要启用模型视图的csv导出,请执行以下操作:
can_export = True
这将给导出记录的模型视图添加一个按钮,在导出最大行(export_max_rows)处截断。
Grouping Views
添加视图时,请为category参数指定一个值,以便在菜单中将相关视图分组在一起:
代码语言:javascript复制admin.add_view(UserView(User, db.session, category="Team"))
admin.add_view(ModelView(Role, db.session, category="Team"))
admin.add_view(ModelView(Permission, db.session, category="Team"))
这将创建一个名为“Team”的顶级菜单项,以及一个包含到三个视图的链接的下拉列表。
要在这些下拉列表中嵌套相关视图,请使用添加子类别方法:
admin.add_sub_category(name="Links", parent_name="Team")
并向菜单添加任意超链接:
admin.add_link(MenuLink(name='Home Page', url='/', category='Links'))
添加自己的视图(Adding Your Own Views)
对于您的需求确实是特定的并且您很难通过内置的ModelView类来满足它们的情况,Flask Admin使您能够轻松地完全控制并将自己的视图添加到界面中。
独立视图(Standalone Views)
通过扩展BaseView类并定义自己的视图方法,可以添加一组独立视图(不绑定到任何特定模型)。例如,要添加显示来自第三方API的某些分析数据的页面,请执行以下操作:
代码语言:javascript复制from flask_admin import BaseView, expose
class AnalyticsView(BaseView):
@expose('/')
def index(self):
return self.render('analytics_index.html')
admin.add_view(AnalyticsView(name='Analytics', endpoint='analytics'))
这将为您的视图添加到导航栏的链接。请注意,它是在根URL的“/”处提供的。这是对独立视图的限制:每个视图类至少需要一个方法来为其根视图提供服务。 上述示例的analytics_index.html模板可能看起来像:
代码语言:javascript复制{% extends 'admin/master.html' %}
{% block body %}
<p>Here I'm going to display some data.</p>
{% endblock %}
通过扩展admin/master.html模板,您可以保持一致的用户体验,即使对页面内容有严格的控制。
覆盖内置视图(Overriding the Built-in Views)
在某些情况下,您可能希望使用大多数内置ModelView功能,但希望替换默认的创建、编辑或列表视图之一。为此,您只能覆盖有问题的视图,并且到该视图的所有链接仍将按预期工作:
代码语言:javascript复制from flask_admin.contrib.sqla import ModelView
# Flask and Flask-SQLAlchemy initialization here
class UserView(ModelView):
@expose('/new/', methods=('GET', 'POST'))
def create_view(self):
"""
Custom create view.
"""
return self.render('create_user.html')
Working With the Built-in Templates
Flask-Admin 使用jinja2模板引擎。
Extending the Built-in Templates
与其完全覆盖内置模板,不如对其进行扩展。这将使您将来更容易升级到新的flask管理版本。 在内部,flask管理模板是从admin/master.html 模板派生的。您要扩展的三个最有趣的模板可能是: admin/model/list.html admin/model/create.html admin/model/edit.html
要使用你自己的功能扩展默认的编辑模板,请请在templates/microblog_edit.html中创建一个模板,其外观如下:
代码语言:javascript复制{% extends 'admin/model/edit.html' %}
{% block body %}
<h1>MicroBlog Edit View</h1>
{{ super() }}
{% endblock %}
现在,要使视图类使用此模板,请设置适当的类属性:
代码语言:javascript复制class MicroBlogModelView(ModelView):
edit_template = 'microblog_edit.html'
# create_template = 'microblog_create.html'
# list_template = 'microblog_list.html'
如果要使用自己的基本模板,请在初始化期间将模板的名称传递给管理构造函数:
admin = Admin(app, base_template='microblog_master.html')
覆盖内置模板(Overriding the Built-in Templates)
要完全控制管理界面的样式和布局,可以覆盖所有内置模板。请记住,模板将从一个版本的flask admin略微更改为下一个版本,因此一旦开始覆盖模板,在升级包版本时需要小心。 要覆盖任何内置模板,只需将它们从Flask-Admin 源复制到项目的templates/admin/目录中。只要文件名保持不变,项目目录中的模板就会自动优先于内置模板。
可用模板块(Available Template Blocks)
Flask-Admin在admin/master.html中定义一个基础模板,所有其他管理模板都是从该模板派生的。此模板是指向admin/base.html的代理,它定义了以下块:
代码语言:javascript复制Block Name Description
head_meta Page metadata in the header
title Page title
head_css Various CSS includes in the header
head Empty block in HTML head, in case you want to put something there
page_body Page layout
brand Logo in the menu bar
main_menu Main menu
menu_links Links menu
access_control Section to the right of the menu (can be used to add login/logout buttons)
messages Alerts and various messages
body Content (that’s where your view will be displayed)
tail Empty area below content
除了从admin/master.html继承的所有块之外,admin/model/list.html模板还包含以下块:
代码语言:javascript复制Block Name Description
model_menu_bar Menu bar
model_list_table Table container
list_header Table header row
list_row_actions_header Actions header
list_row Single row
list_row_actions Row action cell with edit/remove/etc buttons
empty_list_message Message that will be displayed if there are no models found
查看https://github.com/flask-admin/flask-admin/tree/master/examples/custom-layout中的布局示例,了解如何对管理界面进行完全的风格控制。
环境变量(Environment Variables)
在扩展admin/master.html的任何模板中工作时,您可以访问少量的环境变量:
代码语言:javascript复制Variable Name Description
admin_view Current administrative view
admin_base_template Base template name
_gettext Babel gettext
_ngettext Babel ngettext
h Helpers from helpers module
生成URL(Generating URLs)
要为特定视图生成URL,请使用带点前缀的url_for:
代码语言:javascript复制from flask import url_for
class MyView(BaseView):
@expose('/')
def index(self):
# Get URL for the test view method
user_list_url = url_for('user.index_view')
return self.render('index.html', user_list_url=user_list_url)
特定记录也可以通过以下方式引用:
代码语言:javascript复制# Edit View for record #1 (redirect back to index_view)
url_for('user.edit_view', id=1, url=url_for('user.index_view'))
引用ModelView实例时,在调用url_for时,使用模型的小写名称作为前缀。可以通过为每个视图指定一个唯一的端点,并将其用作前缀来引用其他视图。因此,您可以使用:
url_for('analytics.index')
如果视图端点定义如下:
admin.add_view(CustomView(name='Analytics', endpoint='analytics'))