flask_admin使用教程

2020-08-11 14:59:35 浏览数 (1)

安装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'))

0 人点赞