 初始化
初始化
  # 项目创建
# 前端开发模版
我们的项目是基于 pear admin layui 单页版进行开发..
 Pear Admin 是一款开箱即用的前端开发模板!!
pear admin layui 单页版的gitee地址: https://gitee.com/pear-admin/Pear-Admin-Layui

我们打开终端, cmd 到桌面, 执行上述命令 克隆项目到本地. <注意: 我们使用的是main分支 4.0.5的版本 看标签就知道了>
使用pycharm软件打开该项目, 简单看下项目的组成. (gitee上也有解释)

接着, 我们在pychrm里打开终端, 试着运行该项目, 看看效果:
 (PS: 其实直接执行index.html文件也可以看到效果,但我们还是专业点.
在项目根目录下,执行以下命令:
1> sudo cnpm install http-server -g
2> http-server . --port 8080
-- http-server 是一个非常简单的零配置的 HTTP 服务器,可以用于快速服务静态文件。
-- http-server . --port 8080
   http-server: 这个命令调用你刚刚安装的 HTTP 服务器程序
   . : 这个参数表示当前目录. 即服务器将会从当前目录提供文件服务
   --port 8080 : 指定端口
2
3
4
5
6
7
8
9

# 创建Flask项目
利用pycharm使用虚拟环境创建一个新python项目 python版本3.9以上.. 命名为 pear_admin_flask
打开pychrm的终端,会自动进入虚拟环境.. 安装flask pip install flask

在项目根目录下创建 app.py文件, 写入以下代码:
from flask import Flask
def create_app():
    app = Flask(__name__)
    @app.route('/')
    def index():
        return 'hello pear-admin-flask !'
    return app
2
3
4
5
6
7
8
9
10
11
在项目根目录下创建 .flaskenv 文件, 配置启动的环境指令:
FLASK_DEBUG=True                # 开启调试模式,值为True则可以热重载
FLASK_RUN_PORT=5001             # 设置运行的端口
FLASK_RUN_HOST=0.0.0.0          # 设置监听的 ip
FLASK_APP="app:create_app"      # 运行程序  我们创建的app.py所以这里是app 不配置它,默认也是app
2
3
4
在终端运行命令
 pip install python-dotenv
 flask run 启动项目.. (只有安装了python-dotenv,才会去项目根目录下读取 .flaskenv文件!!
 该命令它背后会默认去找app.py里的create_app函数, 运行该函数, 拿到app对象, 执行 app.run()

# 静态文件初始化
★★★ 简单来说..
-1- 纯前端模版就是 http://127.0.0.1:8080/路径 路径去项目根目录下找..
-2- Flask项目, 也是 http://127.0.0.1:8080/路径  但有区别.
     路径以static为前缀,证明去static目录下找静态文件(js、css、图片)..
     没有以static为前缀(eg: html), 则需进行路由匹配,执行相应视图函数!!
# ☆ 思考
首先想一下单纯运行前端开发模版时,它的执行过程
- 运行index.html 
  - <link rel="stylesheet" href="./component/pear/css/pear.css" /> 加载一系列静态资源
    >> http://127.0.0.1:8080/component/pear/css/pear.css
  - admin.setConfigurationPath("config/pear.config.yml"); 加载配置文件
    根据配置发送请求
    - image: "admin/images/logo.png"   去对应的路径下找到相应的静态资源
      >> http://127.0.0.1:8080/admin/images/logo.png
    - href: "view/analysis/index.html" 去对应的路径下运行html文件
      >> http://127.0.0.1:8080/view/analysis/index.html
这些请求去项目对应的路径下就可以直接找到!!
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              // 项目的静态页面目录
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
再思考下, 若将pear admin layui前端模版应用到 Flask项目中,如何做呢?
第一点: Flask的static目录 - 所有html和配置文件中的静态文件(css、js)的路径都要符合Flask的规则
第二点: Flask的templates目录 - 所有的html都要写 一个路由+一个视图函数!!
       ☆ 路由一般写成html在templates目录下的路径
       视图函数找到该html文件要符合Flask templates的规则!
      
- http://127.0.0.1:5001/ 路由匹配的视图函数返回浏览器index.html页面
- 浏览器渲染index.html页面时,发送请求
  - <link rel="stylesheet" href="/static/component/pear/css/pear.css" />
    >> http://127.0.0.1:5001/static/component/pear/css/pear.css 浏览器得到相应的css
  - admin.setConfigurationPath("/static/config/pear.config.json");
    >> http://127.0.0.1:5001/static/config/pear.config.json     浏览器得到配置文件的内容
- 浏览器加载配置文件pear.config.json里的内容
    根据配置发送请求
    - "image": "/static/admin/images/logo.png"
      >> http://127.0.0.1:5001/static/admin/images/logo.png
    - "href": "/view/console/index.html",
      >> http://127.0.0.1:5001/view/console/index.html
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 添加静态资源
我们需要将 pear admin layui 前端开发模版中的 一些文件夹 复制到 我们的Flask项目中!!
首先将 admin、component、config 三个目录复制到 static 目录下
然后将 index.html 、login.html 复制到 templates 目录中
在pychram中将templates目录右键标记为模版文件夹!!

PS: 后续开发过程中需要什么就从前端模版中拿什么!!
接着, 我们需要修正下 html中引入文件的路径!
如何进行修正呢? 很容易想到, 因为 flask 项目默认会读取 static 目录下的静态文件, 且默认以/static为路径前缀..
所以我们只需要 在粘贴过来的html中 将所有静态路径的前面追加 /static/ ..
以index.html为例,eg:
<link rel="stylesheet" href="./component/pear/css/pear.css" />
修正成
<link rel="stylesheet" href="/static/component/pear/css/pear.css"/>
- 若重复在多个html中都用到了,可将这些路径放到 templates/includes/script.html 中,
  使用模版include语法,在index.html中这样写
<head>
    {% include 'includes/script.html' %}
</head>
2
3
4
5
6
7
8
9
10
# 修改数据接口
整体的流程在"思考"小节已经阐述清楚了, 在修改的过程中..
 -1- 要学会打开控制台, 看网络, 哪些没请求到/没修改到..
-2- 修改完后,没有达到自己想要的效果, 点击页面上的退出/自己手动清除cookie和session等浏览器缓存.. 应该就可以解决!

# 调整项目目录结构
可以先去官网看, pear admin flask 项目 main分支最终的成品..
项目地址: https://gitee.com/pear-admin/pear-admin-flask/tree/main/

参照上面截图的目录结构 构建我们的项目的 小蓝图!!
-1- 在项目根目录下创建包pear_admin, 将原先app.py里的内容先剪切到这个包的__init__文件里.. 并删除app.py.
-2- 重新设置.flaskenv 里关于 FLASK_APP 的配置 FLASK_APP="pear_admin:create_app"
     因为pear_admin 是个包, 所以在cmd中运行 flask run 命令时, 会执行 pear_admin 包里 __init__ 里的内容!!
-3- 因为移动了create_app函数所在文件所处的位置, 所以得设置 app=Flask("pear_admin_pear").
     因为设置__name__ , 是以当前文件所在目录去找静态目录和模版目录; 我们在此需改为 以项目根目录为基准!!
-4- 在 pear_admin 下创建views目录, 该目录下的每个py文件都是一个小蓝图!!
     (相当于将原先app.py里的路由函数拆分到这一个个蓝图中!! 别忘了注册蓝图哦!
-5- 在 pear_admin 下再创建 apis、extensions、orms 文件夹, 先准备着, 以后会用!!

# -- .flaskenv
FLASK_DEBUG=True                   # 开启调试模式,值为True则可以热重载
FLASK_RUN_PORT=5001                # 设置运行的端口
FLASK_RUN_HOST=0.0.0.0             # 设置监听的 ip
FLASK_APP="pear_admin:create_app"  # 运行程序  我们创建的app.py所以这里是app
# -- pear_admin/__init__.py
from flask import Flask
from .views.index import index_bp
def create_app():
    app = Flask("pear_admin_flask")
    app.register_blueprint(index_bp)
    return app
# -- pear_admin/views/index.py
from flask import Blueprint, render_template
index_bp = Blueprint('index', __name__)
@index_bp.route('/')
def index():
    return render_template('index.html')
@index_bp.route("/view/console/index.html")  # 工作台
def console():
    return render_template('view/console/index.html')
@index_bp.route("/view/analysis/index.html")  # 分析页
def analysis():
    return render_template('view/analysis/index.html')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# config.py
在编写项目的时候, 一般会运行在多种环境下, 为此最好是将配置文件进行统一..
 比较好的方式是 使用类 进行继承 然后区分, 创建对象, 根据传递的参数再决定使用什么配置文件..
在项目根目录下创建config.py文件..
import os
class BaseConfig:
    SECRET_KEY = os.getenv('SECRET_KEY', 'pear-admin-flask')
    SQLALCHEMY_DATABASE_URI = ""
class DevelopmentConfig(BaseConfig):
    """开发配置"""
    SQLALCHEMY_DATABASE_URI = "sqlite:///pear_admin.db"
    SQLALCHEMY_TRACK_MODIFICATIONS = False
class TestingConfig(BaseConfig):
    """测试配置"""
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'  # 内存数据库
class ProductionConfig(BaseConfig):
    """生成环境配置"""
    SQLALCHEMY_DATABASE_URI = "mysql://root:[email protected]:3306/pear_admin"
    SQLALCHEMY_TRACK_MODIFICATIONS = False
config = {
    'dev': DevelopmentConfig,
    'test': TestingConfig,
    'prod': ProductionConfig
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
然后在 pear_admin/__init__.py 中添加配置
from flask import Flask
from .views.index import index_bp
from configs import config  # 导入配置文件
def create_app(config_name='dev'):
    app = Flask("pear_admin_flask")
    app.config.from_object(config[config_name])  # 加载配置文件
    # print(app.config.get("SQLALCHEMY_DATABASE_URI"))
    app.register_blueprint(index_bp)
    return app
2
3
4
5
6
7
8
9
10
11
12
★ 当我们启动项目之前, 想用哪个配置, 就去.flaskenv 改下. 选一个就好,不传参默认是dev..
FLASK_APP="pear_admin:create_app"
FLASK_APP="pear_admin:create_app('dev')"
FLASK_APP="pear_admin:create_app('test')"
FLASK_APP="pear_admin:create_app('prod')"
2
3
4
# 安装插件 (eg:db)
安装我们这个Flask项目所需要用到的 第三方组件/插件..

pip install flask-sqlalchemy. pip install flask-migrate
初始化数据库插件
# -- pear_admin/extensions/init_db.py
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
# - 初始化数据库相关插件
db = SQLAlchemy()    # ORM操作数据库
migrate = Migrate()  # 数据库迁移
2
3
4
5
6
7
封装到拓展插件目录
# -- pear_admin/extensions/__init__.py
from flask import Flask
from .init_db import db, migrate
# 将初始化的插件对象,封装此处
def register_extensions(app: Flask):
    db.init_app(app)
    migrate.init_app(app, db)
2
3
4
5
6
7
8
9
10
在 app 中配置
from flask import Flask
from .views.index import index_bp
from configs import config  # 导入配置文件
from pear_admin.extensions import register_extensions  # +
def create_app(config_name='dev'):
    app = Flask("pear_admin_flask")
    app.config.from_object(config[config_name])  # 加载配置文件
    # print(app.config.get("SQLALCHEMY_DATABASE_URI"))
    register_extensions(app)  # + 注册插件
    app.register_blueprint(index_bp)  # 注册蓝图
    return app
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 注册蓝图结构优化
# 蓝图少/多
若蓝图比较少, 可以这样做:

若蓝图很多, 可以这样做: (以包的形式去初始化蓝图

# 视图层和接口层
项目的蓝图还可以分为 视图层和接口层..
请求返回 HTML 的路由全部走视图层, 返回的是 json 数据的全部走接口层!!

运行 flask routes 就可以看到显示出来的内容..
(.venv) MacBook-Air:pear_admin_flask dengchuan$ flask routes
Endpoint             Methods  Rule                     
-------------------  -------  -------------------------
api.passport.login   POST     /api/v1/login            
api.passport.logout  POST     /api/v1/logout           
index.analysis       GET      /view/analysis/index.html
index.console        GET      /view/console/index.html 
index.index          GET      /                        
static               GET      /static/<path:filename>  
2
3
4
5
6
7
8
9
目标:将项目上传到gitee上.
- 在gitee上创建同名项目
- 在本地项目中添加 忽略文件.. 提交、推送. 基于http的推送会让你输入用户名密码,正确就推送成功
- 因为是自己一个人维护,所以往后推送以前先拉取!!
2
3
4
提一嘴, 上面关于包的应用 其实就是下面这段代码的封装
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
"""
config.py
"""
class Config:
    # 数据库链接配置参数
    SQLALCHEMY_DATABASE_URI = 'sqlite:///data_04.db'
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    # SQLALCHEMY_ECHO = True
    SECRET_KEY = 'secret key'
app.config.from_object(Config)
"""
插件 - ORM和数据库迁移相关
"""
# 创建数据库链接对象
db = SQLAlchemy()
migrate = Migrate()
db.init_app(app)
migrate.init_app(app, db)
class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(length=20))
    gender = db.Column(db.String(length=20))
    birth = db.Column(db.String(length=20))
    phone = db.Column(db.String(length=20))
    def __repr__(self):
        return '<Student %s>' % self.name
"""
蓝图 - 分为两类<视图和接口>
"""
@app.route('/')
def index():
    return render_template('index.html')
  
  
@app.post('/login')
def login():
    return {'message': '登陆成功', 'code': 200}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
