Flask-Admin后台管理示例
Flask-Admin管理后台示例,主要功能包括,页面汉化,模型字段汉化,搜索,过滤,登录,退出,修改管理员密码,新增管理员用户,分页等功能。
官网地址:Flask-Admin — flask-admin 1.6.0 documentation
官方仓库:http://github.com/flask-admin/flask-admin
功能简介
已实现的功能:
- 通过flask-admin对数据库记录进行增删改查
- flask-admin页面汉化
- 导出内容
- 选择不同的分页大小进行分页
- 添加待管理的模型并将指定列名/字段汉化。
- 登录、退出、修改管理员密码、新增管理员用户
实现的最终效果
文档最开始有代码包,下载后安装环境后即可启动预览,代码布局如下:
基本使用
安装工具包
pip install flask flask-Login Flask-SQLAlchemy flask-babel flask-admin[export] bootstrap-flask
# 需要提前下载到本地
pip install flask_admin-2.0.0a4-py3-none-any.whl
建议:从官方github仓库安装flask-admin最新版,更好的兼容flask3.x和WTForm2.x。当前使用的版本是flask_admin-2.0.0a4。也可以从附件中下载。
以下的代码实现了基础的flask-admin功能,包括页面汉化,模型字段汉化,并开启了一些常用的功能,如搜索,过滤,行内编辑,导出,详情内容查看。添加了flask命令,用户初始化数据库,添加管理员和普通用户。
app.py
from flask import Flask
from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView
from flask_admin.base import Bootstrap4Theme
from flask_sqlalchemy import SQLAlchemy
from flask_babel import Babel
from flask_login import UserMixin
from faker import Faker
import click
app = Flask(__name__)
# 配置数据库信息
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskadmin_example.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'flask-admin'
# 开启后台页面汉化
app.config['BABEL_DEFAULT_LOCALE'] = 'zh_CN'
db = SQLAlchemy(app)
babel = Babel(app)
faker = Faker(app)
# 定义管理员模型
class AdminUsers(db.Model, UserMixin):
__tablename__ = 'admin_users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(200), nullable=False)
def __repr__(self):
return f'<Admin {self.username}>'
# 定义普通用户模型
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(200), nullable=False)
phone_number = db.Column(db.String(20), nullable=False)
city = db.Column(db.String(50), nullable=False)
def __repr__(self):
return f'<User {self.name}>'
# 自定义视图的功能
class UsersModelView(ModelView):
# 开启搜索框,以用户名为条件进行搜索
column_searchable_list = ['username']
# 对username和phone_number开启行内编辑
column_editable_list = ['username', 'phone_number']
# 表单排除的列
form_excluded_columns = ['id']
# 开启过滤功能,以username条件进行过滤
column_filters = ['username']
# 定义显示的列
column_list = ['username', 'phone_number']
# 开启详情查看功能
can_view_details = True
# 列名映射/汉化
column_labels = {
'username': '用户名',
'phone_number': '电话号码',
}
# 开启导出功能
can_export = True
# 设置导出的文件格式
export_types = ['csv', 'json']
# 开启分页功能
can_set_page_size = True
# 设置分页大小选项
page_size_options = [5, 10, 20, 50, 100]
# 默认分页大小
page_size = 5
# name:flask-admin后台的名称
# theme:设置flask-admin的主题,支持的主题在https://bootswatch.com/4/查看
admin = Admin(app, name='管理后台', theme=Bootstrap4Theme(swatch='Cerulean'))
# 将UsersModelView视图添加到flask-admin管理
admin.add_view(UsersModelView(User, db.session, name='用户管理'))
# 初始化数据库
@app.cli.command('init_db')
def init_db():
"""Create the flaskadmin_example database."""
db.drop_all()
db.create_all()
click.echo('Database created successfully!')
# 创建管理员用户
@app.cli.command('create_admin')
@click.option('--username', default='admin')
@click.option('--password', default='admin')
def create_admin(username, password):
"""Create a new admin user."""
admin_user = AdminUsers(username=username, password=password)
db.session.add(admin_user)
db.session.commit()
click.echo(f'Admin user {username}/{password} created successfully!')
# 创建普通用户,默认创建10个用户
@app.cli.command('create_user')
@click.option('--count', default=10)
def create_user(count):
"""Number of users to create."""
for _ in range(count):
user = User(
username=faker.user_name(),
password=faker.password(),
phone_number=faker.phone_number(),
city=faker.city()
)
db.session.add(user)
db.session.commit()
click.echo(f'User {user.username} created successfully!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
接下来初始化数据库,创建管理员用户,创建普通用户
# 初始化数据库
flask init_db
# 创建管理员用户,用户名和密码都是admin,支持通过--username和--password自定义用户名和密码
flask create_admin --username admin --password admin
# 创建普通用户,支持通过--count自定义创建的用户数量
flask create_user --count 10
查看user表
查看admin_users表
运行程序,访问http://127.0.0.1:5000/admin访问管理后台
为首页增加内容,如展示当前的普通用户数量。在templates目录下,创建admin目录,并创建index.html文件。index.html文件内容如下:
{% extends 'admin/master.html' %}
{% block body %}
<div class="container text-center">
<h1>欢迎来到 Flask-Admin 管理后台</h1>
<p>这里是您的管理面板,您可以在此处管理用户和其他资源。</p>
<p>当前用户数量: {{ user_count }}</p>
</div>
{% endblock %}
然后导入AdminIndexView类和expose,创建一个CustomAdminIndexView类,并继承AdminIndexView,编写逻辑,然后使用self.render渲染模板并传参。
app.py
# 导入AdminIndexView, expose
from flask_admin import Admin, AdminIndexView, expose
# 其他未修改的代码这里省略...
# 新增自定义类
class CustomAdminIndexView(AdminIndexView):
@expose('/')
def index(self):
user = User.query.count()
print(f'当前用户数量: {user}')
return self.render('admin/index.html', user_count=user)
# 实例化时,传递自定义的index_view
admin = Admin(app, name='管理后台', theme=Bootstrap4Theme(swatch='Cerulean'), index_view=CustomAdminIndexView())
提示:AdminIndexView类是Admin的首页类,可以覆盖相关的方法重写。
最终实现的效果如下,实际工作中要根据需求定义首页,这里只做示例。
接下来点击用户管理页面,就可以体验配置好的基础功能了。
登录功能
flask-admin默认没有登录鉴权功能,需要手动为flask-admin编写后台登录,登出,修改密码功能。可以使用flask-login扩展来实现。实现的功能要求如下:
- 登录
-
- 未登录无法进入后台管理模型
- 未登录不显示管理的模型,只显示首页
- 登录后显示用户名,点击用户名可以选择修改密码、退出登录、新增管理员
- 退出:登录后,可以退出登录
- 修改密码:登录后,可以修改密码,修改密码后需要重新登录
app.py
# 省略其他包
from flask_bootstrap import Bootstrap4
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired
# 实例化
login_manager = LoginManager(app)
bootstrap = Bootstrap4(app)
# 设置登录加载函数
@login_manager.user_loader
def load_user(user_id):
return AdminUsers.query.get(int(user_id))
# 创建登录表单
class LoginForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired()])
password = PasswordField('密码', validators=[DataRequired()])
submit = SubmitField('登录')
# 创建修改密码表单
class ChangePasswordForm(FlaskForm):
old_password = PasswordField('旧密码', validators=[DataRequired()])
new_password = PasswordField('新密码', validators=[DataRequired()])
confirm_password = PasswordField('确认新密码', validators=[DataRequired()])
submit = SubmitField('修改密码')
# 创建BaseModelView类并继承ModelView,重写is_accessible和inaccessible_callback函数
# 如果认证通过返回true,如果认证不通过重定向到admin.login登录视图
class BaseModelView(ModelView):
def is_accessible(self):
return current_user.is_authenticated
def inaccessible_callback(self, name, **kwargs):
# redirect to login page if user doesn't have access
return redirect(url_for('admin.login', next=request.url))
# 将UserModelView继承类ModelView改为BaseModelView,以便使用重写的认证函数
# 其他新增的模型类也要继承该类。
class UsersModelView(BaseModelView):
# 代码未修改
# 修改CustomAdminIndexView,添加login,logout,change_password函数,重写index函数判断用户是否登录
class CustomAdminIndexView(AdminIndexView):
@expose('/')
def index(self):
if current_user.is_authenticated:
user = User.query.count()
print(f'当前用户数量: {user}')
return self.render('admin/index.html', user_count=user)
return redirect(url_for('admin.login'))
@expose('/login', methods=['GET', 'POST'])
def login(self):
if current_user.is_authenticated:
return redirect(url_for('admin.index'))
form = LoginForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
user = AdminUsers.query.filter_by(username=username).first()
if user and user.password == password:
login_user(user)
flash('您已登录成功!', 'success')
return redirect(url_for('admin.index'))
else:
flash('用户名或密码错误!', 'danger')
return self.render('admin/login.html', form=form)
@expose('/logout/')
def logout(self):
logout_user()
flash('您已成功登出!', 'success')
return redirect(url_for('admin.login'))
@expose('/change_password/', methods=['GET', 'POST'])
def change_password(self):
form = ChangePasswordForm()
if form.validate_on_submit():
current_user.password = form.new_password.data
db.session.commit()
flash('密码修改成功,请重新登录。', 'success')
logout_user() # 修改密码后登出用户
return redirect(url_for('admin.login'))
return self.render('admin/change_password.html', form=form)
@expose('/add_adminuser/', methods=['GET', 'POST'])
def add_adminuser(self):
form = AdminUserForm()
if form.validate_on_submit():
admin_user = AdminUsers(
username=form.username.data,
password=form.password.data
)
db.session.add(admin_user)
db.session.commit()
flash(f'管理员用户{admin_user.username}添加成功!', 'success')
return redirect(url_for('admin.index'))
return self.render('admin/add_adminuser.html', form=form)
在templates/admin目录下添加login.html模板,内容如下
{% extends 'admin/master.html' %}
{% from "bootstrap4/form.html" import render_form %}
{% block title %}管理员登录{% endblock %}
{% block body %}
<div class="container">
<h3>管理员登录</h3>
{{ render_form(form) }}
</div>
{% endblock %}
在templates/admin目录下添加change_password.html模板,内容如下
{% extends 'admin/master.html' %}
{% from "bootstrap4/form.html" import render_form %}
{% block title %}修改密码{% endblock %}
{% block body %}
<div class="container">
<h3>修改密码</h3>
{{ render_form(form) }}
</div>
{% endblock %}
在templates/admin目录下添加master.html模板,用于在导航栏添加登录,退出,修改密码链接。默认的master.html模板是flask-admin提供的,该模板继承admin_base_template,手动在admin目录下创建master.html后,flask-admin会自行使用修改后的master.html,便于自定义。
{% extends admin_base_template %}
{% block menu_links %}
{{ super() }}
<ul class="nav navbar-nav navbar-right">
{% if current_user.is_authenticated %}
<li class="dropdown">
<a class="dropdown-toggle nav-link" data-toggle="dropdown"
href="javascript:void(0)" aria-expanded="false">{{
current_user.username }}<i
class="glyphicon glyphicon-chevron-down small"></i></a>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item"
href="{{ url_for('admin.add_adminuser') }}">
新增管理员</a>
</li>
<li>
<a class="dropdown-item"
href="{{ url_for('admin.change_password') }}">
修改密码</a>
</li>
<li>
<a class="dropdown-item" href="{{ url_for('admin.logout') }}">
退出</a>
</li>
</ul>
</li>
{% else %}
<li>
<a class="nav-link" href="/admin/login">登录</a>
</li>
{% endif %}
</ul>
{% endblock %}
最终实现的效果在文档最前面。
完整示例
app.py
from flask import Flask, url_for, redirect, request, flash
from flask_admin import Admin, AdminIndexView, expose
from flask_admin.contrib.sqla import ModelView
from flask_admin.base import Bootstrap4Theme
from flask_sqlalchemy import SQLAlchemy
from flask_babel import Babel
from flask_login import UserMixin, LoginManager, current_user, login_user, logout_user
from faker import Faker
from flask_bootstrap import Bootstrap4
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired
import click
app = Flask(__name__)
# 配置数据库信息
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskadmin_example.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'flask-admin'
# 开启后台页面汉化
app.config['BABEL_DEFAULT_LOCALE'] = 'zh_CN'
db = SQLAlchemy(app)
babel = Babel(app)
faker = Faker(app)
login_manager = LoginManager(app)
bootstrap = Bootstrap4(app)
# 设置登录加载函数
@login_manager.user_loader
def load_user(user_id):
return AdminUsers.query.get(int(user_id))
# 定义管理员模型
class AdminUsers(db.Model, UserMixin):
__tablename__ = 'admin_users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(200), nullable=False)
def __repr__(self):
return f'<Admin {self.username}>'
# 定义普通用户模型
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(200), nullable=False)
phone_number = db.Column(db.String(20), nullable=False)
city = db.Column(db.String(50), nullable=False)
def __repr__(self):
return f'<User {self.name}>'
class LoginForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired()])
password = PasswordField('密码', validators=[DataRequired()])
submit = SubmitField('登录')
class ChangePasswordForm(FlaskForm):
old_password = PasswordField('旧密码', validators=[DataRequired()])
new_password = PasswordField('新密码', validators=[DataRequired()])
confirm_password = PasswordField('确认新密码', validators=[DataRequired()])
submit = SubmitField('修改密码')
class BaseModelView(ModelView):
def is_accessible(self):
"""检查用户是否有权限访问该视图"""
return current_user.is_authenticated
def inaccessible_callback(self, name, **kwargs):
# redirect to login page if user doesn't have access
return redirect(url_for('admin.login', next=request.url))
# 自定义视图的功能
class UsersModelView(BaseModelView):
# 开启搜索框,以用户名为条件进行搜索
column_searchable_list = ['username']
# 对username和phone_number开启行内编辑
column_editable_list = ['username', 'phone_number']
# 表单排除的列
form_excluded_columns = ['id']
# 开启过滤功能,以username条件进行过滤
column_filters = ['username']
# 定义显示的列
column_list = ['username', 'phone_number']
# 开启详情查看功能
can_view_details = True
# 列名映射/汉化
column_labels = {
'username': '用户名',
'phone_number': '电话号码',
}
# 开启导出功能
can_export = True
# 设置导出的文件格式
export_types = ['csv', 'json']
# 开启分页功能
can_set_page_size = True
# 设置分页大小选项
page_size_options = [5, 10, 20, 50, 100]
# 默认分页大小
page_size = 5
class CustomAdminIndexView(AdminIndexView):
@expose('/')
def index(self):
if current_user.is_authenticated:
user = User.query.count()
print(f'当前用户数量: {user}')
return self.render('admin/index.html', user_count=user)
return redirect(url_for('admin.login'))
# 登录函数
@expose('/login', methods=['GET', 'POST'])
def login(self):
if current_user.is_authenticated:
return redirect(url_for('admin.index'))
form = LoginForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
user = AdminUsers.query.filter_by(username=username).first()
if user and user.password == password:
login_user(user)
flash('您已登录成功!', 'success')
return redirect(url_for('admin.index'))
else:
flash('用户名或密码错误!', 'danger')
return self.render('admin/login.html', form=form)
# 登出函数
@expose('/logout/')
def logout(self):
logout_user()
flash('您已成功登出!', 'success')
return redirect(url_for('admin.login'))
# 修改密码函数
@expose('/change_password/', methods=['GET', 'POST'])
def change_password(self):
form = ChangePasswordForm()
if form.validate_on_submit():
current_user.password = form.new_password.data
db.session.commit()
flash('密码修改成功,请重新登录。', 'success')
logout_user() # 修改密码后登出用户
return redirect(url_for('admin.login'))
return self.render('admin/change_password.html', form=form)
# 新增管理员用户
@expose('/add_adminuser/', methods=['GET', 'POST'])
def add_adminuser(self):
form = AdminUserForm()
if form.validate_on_submit():
admin_user = AdminUsers(
username=form.username.data,
password=form.password.data
)
db.session.add(admin_user)
db.session.commit()
flash(f'管理员用户{admin_user.username}添加成功!', 'success')
return redirect(url_for('admin.index'))
return self.render('admin/add_adminuser.html', form=form)
# name:flask-admin后台的名称
# theme:设置flask-admin的主题,支持的主题在https://bootswatch.com/4/查看
admin = Admin(app, name='管理后台', theme=Bootstrap4Theme(swatch='Cerulean'), index_view=CustomAdminIndexView())
# 将UsersModelView视图添加到flask-admin管理
admin.add_view(UsersModelView(User, db.session, name='用户管理'))
# 初始化数据库
@app.cli.command('init_db')
def init_db():
"""Create the flaskadmin_example database."""
db.drop_all()
db.create_all()
click.echo('Database created successfully!')
# 创建管理员用户
@app.cli.command('create_admin')
@click.option('--username', default='admin')
@click.option('--password', default='admin')
def create_admin(username, password):
"""Create a new admin user."""
admin_user = AdminUsers(username=username, password=password)
db.session.add(admin_user)
db.session.commit()
click.echo(f'Admin user {username}/{password} created successfully!')
# 创建普通用户
@app.cli.command('create_user')
@click.option('--count', default=10)
def create_user(count):
"""Number of users to create."""
for _ in range(count):
user = User(
username=faker.user_name(),
password=faker.password(),
phone_number=faker.phone_number(),
city=faker.city()
)
db.session.add(user)
db.session.commit()
click.echo(f'User {user.username} created successfully!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
html模板的内容参考登录示例即可。

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)