Skip to content

pear admin flask 初始化

flask 项目创建

提示

如果不了解虚拟环境的,可以查看 poetry 入门完全指南

初始化

shell
poetry init

在当前项目目录下创建虚拟环境

shell
poetry config virtualenvs.in-project true
shell
poetry add flask

新建程序实例

python
from flask import Flask


def create_app():
    app = Flask(__name__)

    @app.route('/')
    def index():
        return 'hello pear-admin-flask !'

    return app

开发模式下用以下指令安装依赖

shell
poetry add python-dotenv --group dev

提示

生产环境下使用

shell
poetry install --no-dev

不会安装开发组的依赖

启动的环境指令为下

text
FLASK_DEBUG=True                # 开启调试模式
FLASK_RUN_PORT=5050			    # 设置运行的端口
FLASK_RUN_HOST=0.0.0.0		    # 设置监听的 ip
FLASK_APP="apps:create_app()"   # 运行程序

之后进入虚拟环境(poetry shell),使用 flask run 就可以启动程序。

静态文件初始化

将 pear admin layui 的静态文件复制到项目目录下,并且使用样式启动整个项目。

可以在 pear.config.json 中可以修改主配色

添加静态资源

前端项目地址: https://gitee.com/pear-admin/Pear-Admin-Layui

项目的内容有时候无法保持最新的更新,使用的时候请注意版本是否正确。

首先下载 pear-admin-layui 的项目源码,然后切换到单页版的内容(编写此文档时还是4.x版本),后续可能已经更新到主分支中。

目录的大致结构如下

D:.
│  index.html
│  LICENSE
│  login.html
│  README.md
│  register.html    // 注册页
├─admin
│  ├─css            // css 样式存放位置
│  ├─data           // 数据存放位置
│  └─images         // 静态图片存放位置
├─api               // 测试接口数据存放位置

├─component
│  ├─layui          // layui 文件
│  └─pear
│      │  pear.js   // pear admin layui 的核心 js
│      ├─css        // 项目的核心样式
│      ├─font
│      └─module     // 项目的核心模块目录
│          │
│          └─extends    // 拓展模目录

├─config            // 项目初始化加载的配置文件
│      pear.config.json
│      pear.config.yml

└─view              // 项目的静态页面目录

然后将 admincomponentconfig 三个目录复制到 static 目录下

然后将 index.html 复制到 templates 目录中

首先需要修正一下引入的文件路径。因为 flask 项目的静态文件均放在 static 目录下,所以需要在之前所有的静态路径之前追加 /static/

复制进去之后,将项目中会用到的外源 css、js ,如果使用后端服务器渲染(SSR),可以都都抽取到 templates/includes/script.html

html
<link rel="stylesheet" href="/static/component/pear/css/pear.css"/>
<link rel="stylesheet" href="/static/admin/css/admin.css"/>
<link rel="stylesheet" href="/static/admin/css/admin.dark.css"/>
<link rel="stylesheet" href="/static/admin/css/variables.css"/>
<link rel="stylesheet" href="/static/admin/css/reset.css"/>
<!-- 依 赖 脚 本 -->
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>

然后在 index.html 引入使用

html
<head>
    {% include 'includes/script.html' %}
</head>

这里我们选择前后端分离的方式,就需要在每个页面中自己手动添加引入的完整路径,而不能交给后端进行渲染。

修改接在数据接口

然后翻到最后,修改从后端加载前端配置文件的接口

html
<script>
  layui.use(["admin", "jquery", "popup"], function () {
    var $ = layui.jquery;
    var admin = layui.admin;
    var popup = layui.popup;

    admin.setConfigurationPath("config/pear.config.yml");  
    admin.setConfigurationPath("/static/config/pear.config.json");   

    ...
</script>

pear admin layui 就是从后端加载接口数据,然后渲染前端页面的。可以将数据从静态文件中返回,也可以自定义接口进行返回。 使用自定义接口可以将数据存储在数据库中,修改之后动态生成前端页面数据。

暂时先把项目调通,所以修改一下 /static/config/pear.config.json 的几个路径

json
{
  "logo": {
    "title": "Pear Admin",
    "image": "admin/images/logo.png", 
    "image": "/static/admin/images/logo.png", 
  },
  "menu": {
    "data": "admin/data/menu.json", 
    "data": "/static/admin/data/menu.json", 
    "method": "GET",
    "accordion": true,
    "collapse": false,
    "control": false,
    "controlWidth": 500,
    "select": "10",
    "async": true
  },
  "tab": {
    "enable": true,
    "keepState": true,
    "session": true,
    "preload": false,
    "max": "30",
    "index": {
      "id": "10",
      "href": "view/analysis/index.html",
      "title": "首页"
    }
  },
  "theme": {
    "defaultColor": "2",
    "defaultMenu": "dark-theme",
    "defaultHeader": "light-theme",
    "allowCustom": true,
    "banner": false,
    "dark": true
  },
  "colors": [
    {
      "id": "1",
      "color": "#16baaa",
      "second": "#ecf5ff"
    },
    {
      "id": "2",
      "color": "#009688",
      "second": "#ecf5ff"
    },
    {
      "id": "3",
      "color": "#36b368",
      "second": "#f0f9eb"
    },
    {
      "id": "4",
      "color": "#f6ad55",
      "second": "#fdf6ec"
    },
    {
      "id": "5",
      "color": "#f56c6c",
      "second": "#fef0f0"
    },
    {
      "id": "6",
      "color": "#3963bc",
      "second": "#ecf5ff"
    }
  ],
  "other": {
    "keepLoad": "1200",
    "autoHead": false,
    "footer": false
  },
  "header": {
    "message": "admin/data/message.json"
    "message": "/static/admin/data/message.json"
  }
}

其中 menu.json 的内容如下

json
[
  {
    "id": 1,
    "title": "工作空间",
    "icon": "layui-icon layui-icon-console",
    "type": 0,
    "children": [
      {
        "id": "10",
        "title": "分析页",
        "icon": "layui-icon layui-icon-console",
        "type": 1,
        "openType": "_component",
        "href": "view/analysis/index.html"
      },
      {
        "id": "11",
        "title": "工作台",
        "icon": "layui-icon layui-icon-console",
        "type": 1,
        "openType": "_component",
        "href": "view/console/index.html"
      }
    ]
  }
]

然后复制静态页面到 templates 项目之中,复制完之后的目录如下

templates:.
│  index.html
│  login.html
│  register.html
├─includes
│      script.html
└─view
    ├─analysis
    │      index.html
    └─console
           index.html

然后完善蓝图部分

python
from flask import Blueprint, render_template

index_bp = Blueprint('index', __name__)


@index_bp.route("/")
def index():
    return render_template('index.html')


@index_bp.route("/login.html")
def login():
    return render_template('login.html')


@index_bp.route("/register.html")
def register():
    return render_template('register.html')


@index_bp.route("/view/console/index.html")
def console1():
    return render_template('view/console/index.html')


@index_bp.route("/view/analysis/index.html")
def analysis():
    return render_template('view/analysis/index.html')

代码校验

使用 pre-commit 对 Python 代码校验

shell
poetry add pre-commit --group dev
shell
touch .gitignore
text
.idea/
.venv/
*.py[cod]

新增 .pre-commit-config.yaml 文件,添加下面内容

repos:
  - repo: https://github.com/python/black
    rev: 23.9.1
    hooks:
      - id: black
        language_version: python3.10
  - repo: https://github.com/pycqa/isort
    rev: 5.12.0
    hooks:
      - id: isort
        args: [ "--profile", "black", "--filter-files" ]
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: "v3.0.3"
    hooks:
      - id: prettier
        exclude: >
          (?x)^(
              .*.yaml|
              package-lock.json|
              yarn.lock|
              ^.+\.min\.(js|css)$
          )$
        stages: [ commit ]

代码提交校验

使用 commitizen 格式化 commit message

自定义提交校验

.cz.toml

toml
[tool.commitizen]
name = "cz_customize"
tag_format = "$version"
version_scheme = "pep440"
version_provider = "poetry"
update_changelog_on_bump = true
major_version_zero = true

[tool.commitizen.customize]
message_template = "{{change_type}}{% if scope %}({{scope}}){% endif %}:{% if subject %} {{subject}}{% endif %} {% if footer %} {{footer}}{% endif %}"
example = "feature: this feature enable customize through config file"
schema = "<type>: <body>"
schema_pattern = "(feature|fix|docs|style|refactor|perf|test|revert|build).*?:(\\s.*)"
bump_pattern = "^(break|new|fix|hotfix)"
bump_map = { "break" = "MAJOR", "new" = "MINOR", "fix" = "PATCH", "hotfix" = "PATCH" }
change_type_order = ["BREAKING CHANGE", "feat", "fix", "refactor", "perf"]
info_path = "cz_customize_info.txt"
info = """
This is customized info
"""
commit_parser = "^(?P<change_type>feature|fix|docs|style|refactor|perf|test|revert|build).*?:\\s(?P<message>.*)?"
changelog_pattern = "^(feature|fix|docs|style|refactor|perf|test|revert|build)?(!)?"
change_type_map = { "feature" = "Feat", "bug fix" = "Fix" }


# 自定义提交指令
[[tool.commitizen.customize.questions]]
type = "list"
name = "change_type"
choices = [
    { value = "feature", name = "feature: 新功能" },
    { value = "fix", name = "fix: 修复 bug" },
    { value = "docs", name = "docs: 文档的修改" },
    { value = "style", name = "style: 格式化变动,不影响代码逻辑" },
    { value = "refactor", name = "refactor: 重构,即不是新增功能,也不是修改 bug 的代码变动" },
    { value = "perf", name = "perf: 性能优化" },
    { value = "test", name = "test: 增加测试" },
    { value = "revert", name = "revert: 回退" },
    { value = "build", name = "build: 打包" },
]
# choices = ["feature", "fix"]  # short version
message = "请选择提交类型:"


# 修改内容的范围
[[tool.commitizen.customize.questions]]
type = "input"
name = "scope"
message = "请输入修改内容的范围(可选):"


# 自己的提交内容
[[tool.commitizen.customize.questions]]
type = "input"
name = "subject"
message = "请输入简要描述(必填):"


# 自己的提交内容
[[tool.commitizen.customize.questions]]
type = "input"
name = "body"
message = "请输入详细描述(可选):"


[[tool.commitizen.customize.questions]]
type = "input"
name = "footer"
message = "请输入需要关闭的 issue(可选):"

追加到 .pre-commit-config.yaml

  - repo: https://github.com/commitizen-tools/commitizen
    rev: 3.5.3
    hooks:
      - id: commitizen
        stages: [ commit-msg ]