更多Flask
阅读指南:
Flask基础学习
- 使用virtualenv实现python的虚拟环境
- Python Flask 入门开发
- Python Flask框架配置管理加载的三种方式
- Python Flask 路由配置
- Python Flask静态文件配置
- Python Flask模板渲染
- Python Flask 蓝图Blueprint
- Flask 使用Context上下文
- Flask中SQLAlchemy的使用
Flask 扩展
- 使用flask-script实现Flask项目定制shell功能
- Flask 中使用flask-admin实现数据模型绑定视图
- Flask 中使用mysql数据库
- Flask使用flask-migrate实现数据库迁移
Flask 进阶
Flask
中提供了flask-admin
用来解决在现有数据模型之上构建管理界面的问题。我们只需要写很少的代码,它就可以通过友好的界面来管理web
服务的数据。
Flask-Admin
背后的基本概念是,它允许您通过将各个视图分组到类中来构建复杂的界面:您在前端看到的每个网页都代表一个类上的一个方法,该方法已明确添加到界面中。
这些视图类在绑定到特定数据库模型时特别有用,因为它们允许您将所有常用的创建、读取、更新、删除 (CRUD
) 视图逻辑组合到每个模型的单个、独立的类中。
初始化
首先初始化一个空的管理界面:
from flask import Flask
from flask_admin import Admin
app = Flask(__name__)
# 设置可选的 bootswatch 主题
app.config['FLASK_ADMIN_SWATCH'] = 'cerulean'
admin = Admin(app, name='microblog', template_mode='bootstrap3')
# 在此处添加管理视图
app.run()
这里,name
和 template_mode
参数都是可选的。或者,您可以使用 init_app()
方法。
添加模型视图
模型视图允许您添加一组专用的管理页面来管理数据库中的任何模型。通过创建 ModelView 类的实例来完成此操作,您可以从 Flask-Admin 的内置 ORM 后端之一导入该实例。一个示例是 SQLAlchemy 后端,您可以按如下方式使用它:
from flask_admin.contrib.sqla import ModelView
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name___)
# 增加数据库模型视图
class Users(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
created_at = db.Column(db.TIMESTAMP)
updated_at = db.Column(db.TIMESTAMP)
username = db.Column(db.String(50))
email = db.Column(db.String(50))
nickname = db.Column(db.String(100))
avatar = db.Column(db.String(200))
password_hash = db.Column(db.String(200))
status = db.Column(db.Integer)
def initApp():
db = SQLAlchemy()
db.init_app(app)
admin = Admin(app, name='microblog', template_mode='bootstrap3')
admin.add_view(ModelView(User, db.session))
if __name__ == '__main__':
app.run()
开箱即用,这为您的模型提供了一组功能齐全的 CRUD
视图:
- 列表视图,支持搜索、排序、过滤和删除记录。
- 用于添加新记录的创建视图。
- 用于更新现有记录的编辑视图。
- 可选的只读详细信息视图。
有许多选项可用于自定义这些内置视图的显示和功能。有关更多详细信息,请参阅自定义内置视图。有关可用的其他 ORM
后端的更多详细信息,请参阅使用不同的数据库后端。
将内容添加到索引页
当您访问 http://localhost:5000/admin/
时,您会注意到的第一件事是它只是一个带有导航菜单的空白页面。要向此页面添加一些内容,请将以下文本保存为项目模板目录中的 admin/index.html
:
{% extends 'admin/master.html' %}
{% block body %}
<p>Hello world</p>
{% endblock %}
这将覆盖默认索引模板,但仍会为您提供内置导航菜单。因此,现在您可以向索引页添加任何内容,同时保持一致的用户体验。
授权与权限
为您的应用程序设置管理界面时,您首先要解决的问题之一是如何将不需要的用户拒之门外。使用 Flask-Admin 有几种不同的方法可以解决这个问题。
HTTP 基本认证
不幸的是,没有简单的方法可以将 HTTP Basic Auth
仅应用于您的管理界面。
最简单的身份验证形式是 HTTP Basic Auth
。它不会干扰您的数据库模型,也不需要您编写任何新的视图逻辑或模板代码。因此,当您部署仍在开发中的东西时,它非常适合在您希望全世界看到它之前。
查看 Flask-BasicAuth
,了解将整个应用程序置于 HTTP Basic Auth 之后是多么容易。
自定义访问规则
对于更灵活的解决方案,Flask-Admin
允许您通过简单地覆盖 is_accessible
方法来定义每个管理视图类的访问控制规则。如何实现逻辑取决于您,但如果您要使用像 Flask-Login
这样的低级库,那么限制访问可以像这样简单:
class MicroBlogModelView(sqla.ModelView):
def is_accessible(self):
return login.current_user.is_authenticated
def inaccessible_callback(self, name, **kwargs):
# 如果用户没有访问权限,则重定向到登录页面
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
如果你想要一个更完善的解决方案,你可以使用 Flask-Security
,这是一个更高级别的库。它带有许多内置视图,用于执行用户注册、登录、电子邮件地址确认、密码重置等常见操作。
唯一复杂的一点是让内置的 Flask-Security
视图与 Flask-Admin
模板平滑集成,以创建一致的用户体验。为此,您需要覆盖内置的 Flask-Security
模板,并通过将以下内容添加到每个文件的顶部来让它们扩展 Flask-Admin
基本模板:
{% extends 'admin/master.html' %}
现在,您需要为 Flask-Admin
模板手动传递一些上下文变量,以便在从 Flask-Security
视图调用它们时正确呈现它们。定义一个 security_context_processor
函数将为您解决这个问题:
def security_context_processor():
return dict(
admin_base_template=admin.base_template,
admin_view=admin.index_view,
h=admin_helpers,
)
有关使用 Flask-Security
和 Flask-Admin
的工作示例,请查看 https://github.com/flask-admin/Flask-Admin/tree/master/examples/auth
。
该示例仅使用内置的注册和登录视图,但您可以采用相同的方法来包括其他视图,如忘记密码、发送确认等。
自定义内置视图
从 ModelView
继承时,可以为许多配置参数指定值。使用这些来自定义视图以适合您的特定模型:
from flask_admin.contrib.sqla import ModelView
# 增加数据库模型视图
class Users(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
created_at = db.Column(db.TIMESTAMP)
updated_at = db.Column(db.TIMESTAMP)
username = db.Column(db.String(50))
email = db.Column(db.String(50))
nickname = db.Column(db.String(100))
avatar = db.Column(db.String(200))
password_hash = db.Column(db.String(200))
status = db.Column(db.Integer)
class MicroBlogModelView(ModelView):
can_delete = False # 禁用模型删除
page_size = 50 # 要在列表视图中显示的条目数
admin.add_view(MicroBlogModelView(User, db.session))
或者,以几乎相同的方式,您可以一次为单个模型指定选项:
class UserView(ModelView):
can_delete = False # 禁用模型删除
class PostView(ModelView):
page_size = 50 # 要在列表视图中显示的条目数
admin.add_view(UserView(User, db.session))
admin.add_view(PostView(Post, db.session))
模型视图配置属性
有关已定义属性的完整列表,请查看 BaseModelView()
的 API 文档。以下是一些最常用的属性:
要禁用某些 CRUD
操作,请设置以下任一布尔参数:
can_create = False
can_edit = False
can_delete = False
如果您的模型有太多数据无法在列表视图中显示,您可以通过设置添加只读详细信息视图:
can_view_details = True
从列表视图中删除列很容易,只需为 column_exclude_list 参数传递一个列名列表:
column_exclude_list = ['password', ]
要使列可搜索或使用它们进行过滤,请指定列名列表:
column_searchable_list = ['name', 'email']
column_filters = ['country']
为了获得更快的编辑体验,请在列表视图中启用内联编辑:
column_editable_list = ['name', 'last_name']
或者,让添加和编辑表单显示在列表页面的模态窗口中,而不是专门的创建和编辑页面:
create_modal = True edit_modal = True
您可以通过指定选择列表来限制文本字段的可能值:
form_choices = {
'title': [
('MR', 'Mr'),
('MRS', 'Mrs'),
('MS', 'Ms'),
('DR', 'Dr'),
('PROF', 'Prof.')
]
}
从创建和编辑表单中删除字段:
orm_excluded_columns = ['last_name', 'email']
要指定 WTForms
字段参数:
form_args = {
'name': {
'label': 'First Name',
'validators': [required()]
}
}
或者,为用于呈现这些字段的 WTForms 小部件
指定参数:
form_widget_args = {
'description': {
'rows': 10,
'style': 'color: black'
}
}
当您的表单包含外键时,通过 ajax
加载那些相关模型,使用:
form_ajax_refs = {
'user': {
'fields': ['first_name', 'last_name', 'email'],
'page_size': 10
}
}
要过滤通过 ajax
加载的结果,您可以使用:
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
处截断。
分组视图
添加视图时,为类别参数指定一个值以将菜单中的相关视图组合在一起:
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"))
这将创建一个名为“团队”的顶级菜单项,以及一个包含指向三个视图的链接的下拉菜单。要在这些下拉列表中嵌套相关视图,请使用 add_sub_category
方法:
admin.add_sub_category(name="Links", parent_name="Team")
并向菜单添加任意超链接:
admin.add_link(MenuLink(name='Home Page', url='/', category='Links'))
添加您自己的视图
对于您的需求非常具体并且您很难通过内置的 ModelView
类来满足它们的情况,Flask-Admin
使您可以轻松地完全控制并向界面添加您自己的视图。
单例视图
可以通过扩展 BaseView
类并定义您自己的视图方法来添加一组独立视图(不依赖于任何特定模型)。例如,要添加一个显示来自第 3 方 API
的一些分析数据的页面:
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 模板可能类似于:
{% extends 'admin/master.html' %}
{% block body %}
<p>Here I'm going to display some data.</p>
{% endblock %}
通过扩展 admin/master.html
模板,即使在严格控制页面内容的情况下,您也可以保持一致的用户体验。
覆盖内置视图
在某些情况下,您可能需要大部分内置的 ModelView
功能,但又想替换默认的创建、编辑或列表视图之一。为此,您可以仅覆盖有问题的视图,并且指向它的所有链接仍将按您期望的那样运行:
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):
"""
自定义创建视图。
"""
return self.render('create_user.html')
使用内置模板
Flask-Admin
使用 Jinja2
模板引擎。
扩展内置模板
与其完全覆盖内置模板,不如扩展它们。这将使您将来更容易升级到新的 Flask-Admin
版本。在内部,Flask-Admin
模板派生自 admin/master.html
模板。您可以扩展的三个最有趣的模板可能是:
admin/model/list.html
admin/model/create.html
admin/model/edit.html
要使用您自己的功能扩展默认编辑模板,请在 templates/microblog_edit.html
中创建一个类似于以下内容的模板:
{% extends 'admin/model/edit.html' %}
{% block body %}
<h1>MicroBlog Edit View</h1>
{{ super() }}
{% endblock %}
现在,要让您的视图类使用此模板,请设置适当的类属性:
class MicroBlogModelView(ModelView):
edit_template = 'microblog_edit.html'
# create_template = 'microblog_create.html'
# list_template = 'microblog_list.html'
# details_template = 'microblog_details.html'
# edit_modal_template = 'microblog_edit_modal.html'
# create_modal_template = 'microblog_create_modal.html'
# details_modal_template = 'microblog_details_modal.html'
如果要使用自己的基本模板,则在初始化期间将模板的名称传递给管理构造函数:
admin = Admin(app, base_template='microblog_master.html')
覆盖内置模板
要完全控制管理界面的样式和布局,您可以覆盖所有内置模板。请记住,从一个版本的 Flask-Admin
到下一个版本,模板会略有不同,因此一旦开始覆盖它们,升级包版本时需要小心。
要覆盖任何内置模板,只需将它们从 Flask-Admin
源复制到项目的 templates/admin/
目录中。只要文件名保持不变,项目目录中的模板就会自动优先于内置模板。
可用模板代码块
Flask-Admin
在 admin/master.html
中定义了一个基本模板,所有其他管理模板都派生自该模板。这个模板是一个指向 admin/base.html
的代理,它定义了以下代码块:
代码块名 | 描述 |
---|---|
head_meta | 页眉中的页面元数据 |
title | 页面标题 |
head_css | 标头中包含各种 CSS |
head | HTML head 中的空块,以防你想在那里放一些东西 |
page_body | 页面布局 |
brand | 菜单栏中的徽标 |
main_menu | 主菜单 |
menu_links | 链接菜单 |
access_control | 菜单右侧的部分(可用于添加登录/注销按钮) |
messages | 警报和各种消息 |
body | 内容(即您的视图将显示的位置) |
tail | 内容下方空白区域 |
除了从 admin/master.html
继承的所有块之外,admin/model/list.html
模板还包含以下代码块:
代码块名 | 描述 |
---|---|
model_menu_bar | 菜单栏 |
model_list_table | 表格容器 |
list_header | 表格标题行 |
list_row_actions_header | 操作标题 |
list_row | 单排 |
list_row_actions | 带有编辑/删除/等按钮的行操作单元格 |
empty_list_message | 如果没有找到模型,将显示的消息 |
查看 https://github.com/flask-admin/flask-admin/tree/master/examples/custom-layout
中的布局示例,了解如何对管理界面进行全面的风格控制。
环境变量
在使用任何扩展 admin/master.html
的模板时,您可以访问少量环境变量:
变量名 | 描述 |
---|---|
admin_view | 当前管理视图 |
admin_base_template | 基本模板名称 |
_gettext | Babel gettext |
_ngettext | Babel ngettext |
h | 帮助文档来自helpers 模块 |
生成网址
为特定视图生成 URL
,请使用带点前缀的 url_for
:
from flask import url_for
class MyView(BaseView):
@expose('/')
def index(self):
#获取测试视图方法的 URL
user_list_url = url_for('user.index_view')
return self.render('index.html', user_list_url=user_list_url)
还可以通过以下方式引用特定记录:
# 编辑记录 #1 的视图(重定向回 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'))
评论前必须登录!
注册