第一课 python-Flask的MTV拆分

Flask 第一课项目MVC拆分

tags:

  • Flask
  • 2019千锋教育

categories:

  • flask
  • MVC
  • 项目拆分

第一节 flask的Hello world

1. flask基本知识

  1. Flask是一一个基于Python实现的Web开发‘微’框架
  2. 官方文档: http://flask.pocoo.org/docs/0.12/
  3. 中文文档: http://docs.jinkan.org/docs/flask/
  4. Flask和Django 样,也是一个基于MVC设计模式的Web框架
  5. Flask依赖三个库
    • Jinja2模板引擎
    • Werkzeug WSGI工具集
    • ltsdangerous; 基于Django的签名模块
  6. MVC的设计模式目的是解耦:把用户逻辑、页面展示、数据库操作拆开来写。
from flask import Flask  #导入flask

app = Flask(__name__)

#装饰器,用作url与视图函数的映射,一般写在函数上方
@app.route('/')
def index():
    return 'Hello Flask'


#主函数,运行后在浏览器输入127.0.0.1:5000(或者进入控制台显示的地址即可)
#debug是否开启调试模式,开启后修改过python代码会自动重启
#threaded是否开启多线程
#port启动指定服务器的端口号
#host主机,默认是127.0.0.1, 指定为0.0.0.0代表所有ip可以连接本机
if __name__ == '__main__':
    app.run()
  1. 开启debug. 会有一个PIN(密码)如下图:用于页面调试输入
	return os.environ.get("FLASK_ENV") or "production"
  1. 这里有个Environment: production。 其实只要修改系统的环境变量FLASK_ENV
    在这里插入图片描述
  2. 调试器有保护功能,页面调试如下
    在这里插入图片描述
  3. 可以在网页中输出变量进行查看
    在这里插入图片描述

第二节 Flask的命令行工具

1. 命令行工具flask-script

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

2. 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()
  1. 直接运行脚本,已经不能启动项目。(需要用命令行来启动命令)
  2. 使用命令: python manager.py runserver
  3. python manager.py runserver --help (查看可用命令)
  4. 如:(-h HOST, --host HOST) (-p PORT, --port PORT ) (–threaded) (-d, --debug)

第三节 第一阶段_拆路由

1. 着手拆分

  1. 项目目录创建如下。
    在这里插入图片描述
  2. 把路由写到views 文件中
# views.py
from manage import app

@app.route('/')
def index():
    return 'Hello Flask'
  1. 运行:python manager.py runserver 报错截图如下.(这是因为views根本没有注册到app中,app根本不知道views文件的存在)
    在这里插入图片描述

2. 尝试解决

  1. 尝试解决方法一:
    • 直接在manage.py 中导入路由函数。from App.views import index
    • 结果报错:ImportError: cannot import name ‘index’
    • 报错原因:循环导入(你导我,我导你)
  2. 尝试对代码做一些变换:
    • 把manage.py的注册app的代码移动到项目的初始化文件__init__.py中
# 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()
  1. 这时候views依然没有导入,如果直接在__init__.py中引入views。依然没有解决循环引用的问题。
    在这里插入图片描述

3. 解决方案一:懒加载

  1. 直接在views.py中, 通过函数把app的值传过来
# views.py
def init_route(app):
    @app.route('/')
    def index():
        return 'Hello Flask'
  1. 在__init__.py中引入初始化函数,把app的值传过去。这样的化views.py就没有导入app了。
# 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. 解决方案二:蓝图flask-blueprint

  1. 下载flask-blueprint: pip install flask-blueprint -i https://pypi.douban.com/simple
  2. 蓝图是比较流行的一种方式。
  3. 修改views.py文件,注册蓝图。
# views.py
from flask import Blueprint, render_template


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


@blue.route('/')
def index():
    return '我是蓝图的主页!'
    #渲染模板和传参 {{ msg }}
    #return render_template('index.html', msg="今天天气好")
  1. 在__init__.py中导入蓝图并注册蓝图。
from flask import Flask
from App.views import blue


def create_app():
    app = Flask(__name__)
    # 注册蓝图
    app.register_blueprint(blue)
    return app
  1. pycharm小技巧,把文件变成python包。用这种方法可以把蓝图划分成不同的蓝图路由。
    在这里插入图片描述

第四节 第二阶段_拆数据模型

1.数据模型构建

  1. 安装flask-sqlalchemy:pip install flask-sqlalchemy -i https://pypi.douban.com/simple
  2. 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))  # 密码
  1. 和上面views同样的问题, app这里需要引入。还需要把models注册到app中构成循环引用。

2. 官方方案之懒加载

  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))  # 密码
  1. 官方给出了解决方案如下:
# 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))  # 密码
  1. 在__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_test'
    # 保持兼容性
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    init_model(app)
    return app
  1. 通过路由创建数据表。提前先构建一个数据库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 '创建数据表成功'

第五节 第三阶段_分离配置和第三方库(包括上面的models)

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

正常练手项目使用此拆分已经可以足够完成

  1. 创建配置文件settings.py
  2. 创建第三方库文件ext.py
  3. 分离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))  # 密码
  1. ext.py文件中放入需要导入的第三方库如:models初始化SQLAlchemy库
# ext.py
from flask_sqlalchemy import SQLAlchemy

models = SQLAlchemy()


def init_ext(app):
    # 懒加载模型
    models.init_app(app=app)
  1. 在__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 '创建数据表成功'
  1. 模型可用的原因:views中导入了models
    在这里插入图片描述

2. 分离配置出__init__.py

公司开发产品使用此拆分供多种人员使用

  1. 公司中常常需要配置多套环境。

    • 开发环境(开发人员使用)
    • 测试环境(测试人员使用)
    • 演习环境(给产品看的)
    • 生产环境 (又叫线上环境给用户使用)
  2. 把四套环境的配置写到配置文件的settings.py中。

def get_db_uri(dbinfo):
    engine = dbinfo.get("ENGINE") or "mysql"
    driver = dbinfo.get("DRIVER") or "pymysql"
    user = dbinfo.get("USER") or "root"
    password = dbinfo.get("PASSWORD") or "123456"
    host = dbinfo.get("HOST") or "localhost"
    port = dbinfo.get("PORT") or "3306"
    dbname = dbinfo.get("DBNAME") or "flask_test"
    # uri数据库+驱动://用户名:密码@主机:端口/具体哪一个库
    return '{}+{}://{}:{}@{}:{}/{}'.format(engine, driver, user, password, host, port, dbname)


class Config:
    DEBUG = False
    TESTING = False
    SQLALCHEMY_TRACK_MODIFICATIONS = False


# 开发环境
class DevelopConfig(Config):
    DEBUG = True

    dbinfo = {
        "ENGINE": "mysql",
        "DRIVER": "pymysql",
        "USER": "root",
        "PASSWORD": "123456",
        "HOST": "127.0.0.1",
        "PORT": "3306",
        "DBNAME": "flask_test"
    }

    SQLALCHEMY_DATABASE_URI = get_db_uri(dbinfo)


# 测试环境
class TestConfig(Config):

    dbinfo = {
        "ENGINE": "mysql",
        "DRIVER": "pymysql",
        "USER": "root",
        "PASSWORD": "123456",
        "HOST": "127.0.0.1",
        "PORT": "3306",
        "DBNAME": "flask_test"
    }

    SQLALCHEMY_DATABASE_URI = get_db_uri(dbinfo)


# 演示环境
class StageConfig(Config):

    dbinfo = {
        "ENGINE": "mysql",
        "DRIVER": "pymysql",
        "USER": "root",
        "PASSWORD": "123456",
        "HOST": "127.0.0.1",
        "PORT": "3306",
        "DBNAME": "flask_test"
    }

    SQLALCHEMY_DATABASE_URI = get_db_uri(dbinfo)


# 线上(生产)环境
class ProductConfig(Config):

    dbinfo = {
        "ENGINE": "mysql",
        "DRIVER": "pymysql",
        "USER": "root",
        "PASSWORD": "123456",
        "HOST": "127.0.0.1",
        "PORT": "3306",
        "DBNAME": "flask_test"
    }

    SQLALCHEMY_DATABASE_URI = get_db_uri(dbinfo)
    
   
envs = {
    "develop": DevelopConfig,
    "testing": TestConfig,
    "staging": StageConfig,
    "product": ProductConfig,
    "default": DevelopConfig
}
  1. 把配置文件写到__init__.py文件中去。
from flask import Flask
from App.views import blue
from App.ext import init_ext
from App.settings import envs


def create_app():
    app = Flask(__name__)
    app.register_blueprint(blue)
    # uri数据库+驱动://用户名:密码@主机:端口/具体哪一个库
    #app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:[email protected]:3306/flask_test'
    # 保持兼容性
    #app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    app.config.from_object(envs.get("develop"))
    init_ext(app=app)
    return app
  1. 配置文件中的envs.get(“develop”),可以通过变量形式传入(比如获取当前电脑的环境变量,或者传入一个需要的环境)。
# __init__.py
from flask import Flask
from App.views import blue
from App.ext import init_ext
from App.settings import envs


def create_app(env):
    app = Flask(__name__)
    app.register_blueprint(blue)
    # uri数据库+驱动://用户名:密码@主机:端口/具体哪一个库
    #app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:[email protected]:3306/flask_test'
    # 保持兼容性
    #app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    app.config.from_object(envs.get(env))
    init_ext(app=app)
    return app
# manage.py
from flask_script import Manager
from App import create_app
import os

# 这样做的好处是,在开发的电脑上就是开发环境。在测试电脑上就是测试环境。
# 前提需要配置环境变量的值FLASK_ ENV。
env = os.environ.get("FLASK_ ENV", "develop")

app = create_app(env)
manager = Manager(app)


if __name__ == '__main__':
    manager.run()

第六节 拓展添加Flask-migrate库

1. 增加数据库迁移功能

  1. Flask-migrate库用于拓展flask的数据库的类似django的迁移功能。
  2. pip install flask-migrate -i https://pypi.douban.com/simple
  3. 它和Flask-Script可以配合使用。from flask_migrate import MigrateCommand
  4. 操作命名db命令,manager.add_command(‘db’, MigrateCommand)
  5. 在ext.py中注册
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

models = SQLAlchemy()
migrate = Migrate()


def init_ext(app):
    # 懒加载模型
    models.init_app(app=app)
    migrate.init_app(app, models)
  1. 在manage.py中绑定命令
from flask_script import Manager
from App import create_app
from flask_migrate import MigrateCommand
import os


# 这样做的好处是,在开发的电脑上就是开发环境。在测试电脑上就是测试环境。
# 前提需要配置环境变量的值FLASK_ ENV。
env = os.environ.get("FLASK_ ENV", "develop")

app = create_app(env)
manager = Manager(app)
manager.add_command('db', MigrateCommand)


if __name__ == '__main__':
    manager.run()
  1. 运行python manage.py runserver --help
    在这里插入图片描述
  2. 初始化数据库:python manage.py db init
  3. 生成迁移文件:python manage.py db migrate
  4. 生成数据库:python manage.py db upgrade

2. odoo框架介绍

  1. 比django还重的框架。
  2. 可以一键生成网站
发布了61 篇原创文章 · 获赞 8 · 访问量 2818

猜你喜欢

转载自blog.csdn.net/aa18855953229/article/details/103997715
今日推荐