MVC目录格式(FlaskMTV)
in FlaskPython with 0 comment
MVC目录格式(FlaskMTV)
in FlaskPython with 0 comment

MTV(Model–Template–View)也就是 MVC框架 (模型、模板、视图)

MVC设计目的是:Model(模型)View(视图)Controller(控制器)

对项目工程进行拆分,降低耦合性。

实现目录格式化,需要先掌握修改文件路由。

第一阶段

Flask的命令行工具

  1. 命令行工具flask-script

debug是否开启调试模式,开启后修改过python代码会自动重启
threaded是否开启多线程
port启动指定服务器的端口号
host主机,默认是127.0.0.1, 指定为0.0.0.0代表所有ip可以连接本机
下载flask-script: pip install flask-script
初始化:使用app 构建Manage对象。manager = Manager(app)
运行:manager.run()

  1. flask-script使用

    from flask import Flask
    from flask_script import Manager
    
    app = Flask(__name__)
    manager = Manager(app)
    
    @app.route('/')
    def index():
     return 'Hello Flask'
    
    if __name__ == '__main__':
     manager.run()

    直接运行脚本,已经不能启动项目。(需要用命令行来启动命令)
    使用命令: python manager.py runserver
    python manager.py runserver --help (查看可用命令)

如:(-h HOST, --host HOST) (-p PORT, --port PORT ) (–threaded) (-d, --debug)

拆分路由

1.先拆分目录(没有的文件自行创建)

2.把路由写到 views.py 文件中

# -*- coding:utf-8 -*-
# Steam: LceAn
# Time: 2021/5/11 13:31
# name: views.py
# Path: PyCharm
# MVC/app/views.py

from manage import app

@app.route('/')
def index():
    return 'Hello LceAn'

Ps:此时 使用命令运行manage.py 会报错,并不能启动web,因为views并没有注册到app中,app不知道自己有这个文件

2-1.加入路由

在manage.py中加入路由: from app.views import index
运行,仍报错,报错原因为循环导入。(manage导入views,views又 导入manage)
2-2.尝试代码进行优化

把manage.py中 注册app的代码 转移到项目初始化 __init__.py 文件中

# -*- coding:utf-8 -*-
# Steam: LceAn
# Time: 2021/5/11 13:28
# name: __init__.py
# Path: PyCharm
# MVC/app/__init__.py

from flask import Flask

def create_app():
    app = Flask(__name__)
    return app

在 manage.py 中引入create_app()

from app import create_app
app = create_app()

这时候views还是没有被引入,死循环依旧存在。

Ps:如图
1
死循环,manage路由指向__init__,__init__路由指向views,而views路由却指回了__init__

  1. 解决方案一 : 懒加载(使用函数传递)

3-1.直接在 views.py 中,通过函数init_rout把app的值传进来

# -*- coding:utf-8 -*-
# Steam: LceAn
# Time: 2021/5/11 13:31
# name: views.py
# Path: PyCharm
# MVC/app/views.py

def init_route(app):
    @app.route('/')
    def index():
        return 'Hello Lcean'

3-1.在 __init__.py 中引入初始化函数, 把 app 的值传过去。这样 views.py 就没有导入app了(导入的是app的参数,而不是本身的app函数)

# -*- coding:utf-8 -*-
# Steam: LceAn
# Time: 2021/5/11 13:28
# name: __init__.py.py
# Path: PyCharm
# MVC/app/__init__.py

from flask import Flask
from app.views import init_route

def create_app():
    app = Flask(__name__)
    init_route(app)
    return app

路由实现拆分,逻辑如图(虽实现,但是不是很好,所有的路由都在一起,并没有完全拆分)

4.解决方案二:

1.需要用到新的模板(蓝图)flask-blueprint

pip install flask-blueprint
Ps:蓝图是现在笔记主流的方式

2.修改 views.py 文件,注册蓝图。

# MVC/app/views.py
from flask import Blueprint, render_template


# 申明一个蓝图对象
blue = Blueprint('blue', __name__)


@blue.route('/')
def index():
    return '蓝图的主页!'

3.在 __init__.py 中导入蓝图并注册蓝图

from flask import Flask
from App.views import blue


def create_app():
    app = Flask(__name__)
    # 注册蓝图
    app.register_blueprint(blue)
    return app

4.运行 manage.py 查看效果

第二阶段

拆数据模型

1.数据模型构建

安装flask-sqlalchemy: pip install flask-sqlalchemy
model.py也是由app实例构建的,实现一个数据库模型:

from manage import app
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy(app)

# 会员数据模型
class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)  # 编号
    username = db.Column(db.String(100), unique=True)  # 昵称
    password = db.Column(db.String(100))  # 密码

Ps:和上面views同样的问题, app这里需要引入。还需要把models注册到app中构成循环引用。

  1. 官方方案之懒加载

假如不加修改采用我们之前的懒加载模式models.py代码如下。会出现db没有定义为全局变量的问题。

# models.py
from flask_sqlalchemy import SQLAlchemy

def init_model(app):
    db = SQLAlchemy(app)

# 会员数据模型
class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)  # 编号
    username = db.Column(db.String(100), unique=True)  # 昵称
    password = db.Column(db.String(100))  # 密码

官方给出了解决方案如下:

# models.py
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

# 官方的解决方案
def init_model(app):
    db.init_app(app=app)


# 会员数据模型
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)  # 编号
    username = db.Column(db.String(100), unique=True)  # 昵称
    password = db.Column(db.String(100))  # 密码

在__init__.py中引入初始化函数和数据库的配置。把init_model导过去传值app。

# __init__.py
from flask import Flask
from App.views import blue
from App.models import init_model


def create_app():
    app = Flask(__name__)
    app.register_blueprint(blue)
    # uri数据库+驱动://用户 名:密码@主机:端口/具体哪一个库
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:[email protected]:3306/flask'
    # 保持兼容性
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    init_model(app)
    return app

通过路由创建数据表。提前先构建一个数据库flask_test.运行后生产user表。

# views.py
from flask import Blueprint
from App.models import db


# 申明一个蓝图对象
blue = Blueprint('blue', __name__)


@blue.route('/createdb')
def createdb():
    db.create_all()
    return '创建数据表成功'

第三阶段

分离配置和第三方库

1.分离第三方库出 __init__.py

创建配置文件settings.py
创建第三方库文件ext.py
分离models.py中的一些模型初始化,这里把views看成内置模块就放在__init__.py文件中。为了和django模型保持一致。这里也把上面的db变成models。

#models.py
from App.ext import models


# 会员数据模型
class User(models.Model):
    id = models.Column(models.Integer, primary_key=True)  # 编号
    username = models.Column(models.String(100), unique=True)  # 昵称
    password = models.Column(models.String(100))  # 密码

ext.py文件中放入需要导入的第三方库如:models初始化SQLAlchemy库

# ext.py
from flask_sqlalchemy import SQLAlchemy

models = SQLAlchemy()


def init_ext(app):
    # 懒加载模型
    models.init_app(app=app)
 
在__init__.py中懒加载ext.py中的init_ext。函数
# __init__.py
from flask import Flask
from App.views import blue
from App.ext import init_ext


def create_app():
    app = Flask(__name__)
    # uri数据库+驱动://用户 名:密码@主机:端口/具体哪一个库
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:[email protected]:3306/flask_test'
    # 保持兼容性
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    init_ext(app=app)
    app.register_blueprint(blue)
    return app
# views.py
from flask import Blueprint, render_template
# 这里注意要导入models中的models,而不是刚刚注册的ext中的models
from App.models import models


# 申明一个蓝图对象

blue = Blueprint('blue', __name__)


@blue.route('/')
def index():
    #渲染模板和传参 {{ msg }}
    #return render_template('index.html', msg="今天天气好")
    return 'Hello Flask'


@blue.route('/createdb')
def createdb():
    models.create_all()
    return '创建数据表成功'

模型可用的原因:views中导入了models

Responses