57

返回主页
iR.Poke
博客园
首页
新随笔
联系
订阅
管理
day98:MoFang:服务端项目搭建

目录

1.准备工作

2.创建项目启动文件manage.py

3.构建全局初始化函数并在函数内创建app应用对象

4.通过终端脚本启动项目

5.项目加载配置

6.数据库初始化

1.SQLAlchemy初始化

2.Redis初始化

3.session存储到redis数据库中

4.数据迁移初始化

7.日志初始化

8.蓝图初始化

1.通过终端命令创建蓝图,并在蓝图中生成view/model/url等文件

2.将蓝图注册到APP应用对象下

3.注册路由和视图之间的关系

4.自动注册蓝图下的所有模型

1.准备工作

1.新建项目目录mofangapi,并创建虚拟环境

mkvirtualenv mofang
2.安装开发中使用的依赖模块

复制代码
pip install flask==0.12.4
pip install flask-redis
pip install flask-session
pip install flask-script
pip install flask-mysqldb
pip install flask-sqlalchemy
pip install flask-migrate
复制代码
接下来,在pycharm中打开项目目录mofangapi编写manage.py启动项目的文件

2.创建项目启动文件manage.py

复制代码
from flask import Flask

app = Flask(name)

@app.route(’/’)
def index():
return ‘index’

if name == ‘main’:
app.run()
复制代码
manage.py终不能存放大量的开发代码, 在开发中应该体现的是一种分工精神,所以我们可以把flask中各种功能代码进行分类分文件存储.

现在项目的目录结构如下所示:

复制代码
项目根目录/
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prod.py # 生产阶段的配置文件
| | ├ init.py # 项目公共配置文件
│ ├── init.py # 项目初始化文件
├── manage.py # 项目的终端管理脚本文件
复制代码
3.构建全局初始化函数并在函数内创建app应用对象

1.把引导整个项目启动的全局初始化代码,保存到application/__init__py,代码:

复制代码
from flask import Flask

def init_app():
“”“全局初始化”""
app = Flask(name) # 创建APP应用对象
return app
复制代码
2.在manage.py,中调用初始化函数,创建app应用对象,代码:

复制代码
from application import init_app

app = init_app() # 创建app应用对象

@app.route(’/’)
def index():
return ‘index’

if name == ‘main’:
app.run()
复制代码
4.通过终端脚本启动项目

applicatiion/__init__py,代码:

复制代码
from flask import Flask
from flask_script import Manager

manager = Manager() # 引入终端脚本管理对象 ***

def init_app():
“”“全局初始化”""

# 创建app应用对象
app = Flask(__name__)

# 初始化终端脚本工具 ***
manager.app = app

return manager

复制代码
将manage.py的app改为manage,代码:

复制代码
from application import init_app

manage = init_app()

@manage.app.route(’/’)
def index():
return ‘index’

if name == ‘main’:
manage.run()
复制代码
运行项目的方式就要修改如下:

此时我们就可以通过如下指令去运行项目了

python manage.py runserver -h0.0.0.0 -p5000
5.项目加载配置

1.在application/utils/config.py中准备加载配置的函数代码:

复制代码
from importlib import import_module
def load_config(config_path):
“”“自动加载配置”""
module = import_module(config_path)
name = config_path.split(".")[-1]
if name == “settings”:
return module.InitConfig
else:
return module.Config
复制代码
2.编写项目默认配置文件, application/settings/init.py代码:

class InitConfig():
“”“项目默认初始化配置”""
DEBUG = True
当然, 项目开发过程完成以后肯定会项目上线,所以针对配置文件,我们可以准备不同环境下的配置

application/settings/dev.py,代码:

from . import InitConfig
class Config(InitConfig):
“”“项目开发环境下的配置”""
DEBUG = True
application/settings/prod.py,代码:

from . import InitConfig
class Config(InitConfig):
“”“项目运营环境下的配置”""
DEBUG = False
3.在项目引导文件application/__init__py中加载配置,代码:

复制代码
from flask import Flask
from flask_script import Manager
from application.utils.config import load_config
manager = Manager()

def init_app(config_path):
“”“全局初始化”""
# 创建app应用对象
app = Flask(name)

# 设置项目根目录
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 加载配置 ****
Config = load_config(config_path) # 调用utils里自己已经写好的load_config方法
app.config.from_object(Config) # 将配置类注册到APP上

# 初始化终端脚本工具
manager.app = app

return manager

复制代码
4.在创建app对象的项目启动文件manage.py中,设置配置

复制代码
from application import init_app

manage = init_app(“application.settings.dev”) # 设置默认项目使用的配置文件是dev.py

@manage.app.route(’/’)
def index():
return ‘index’

if name == ‘main’:
manage.run()
复制代码
6.数据库初始化

1.SQLAlchemy初始化

1.默认项目配置文件中增加配置选项,application/settings/init.py,代码:

复制代码
class InitConfig():
“”“项目默认初始化配置”""
# 调试模式
DEBUG = True

# 数据库相关配置
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= True

复制代码
2.开发配置dev.py中,配置数据库连接信息,代码:

复制代码
from . import InitConfig
class Config(InitConfig):
“”“项目开发环境下的配置”""
DEBUG = True
# 数据库
SQLALCHEMY_DATABASE_URI = “mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4”
SQLALCHEMY_ECHO = True
复制代码
3.在mysql终端下, 创建数据库用户,命令如下:

create database mofang charset=utf8mb4;

针对当前数据库配置账户信息

create user mofang_user identified by ‘mofang’;
grant all privileges on mofang.* to ‘mofang_user’@’%’;
flush privileges;
4.在项目全局引导文件中,对数据库功能进行初始化,application/init.py,代码:

复制代码
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from application.utils.config import load_config

创建终端脚本管理对象

manager = Manager()

创建数据库链接对象 ***

db = SQLAlchemy()

def init_app(config_path):
“”“全局初始化”""

# 创建app应用对象
app = Flask(__name__)
# 项目根目录
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 加载配置
Config = load_config(config_path)
app.config.from_object(Config)

# 数据库初始化 ***
db.init_app(app)

# 初始化终端脚本工具
manager.app = app

return manager

复制代码
2.Redis初始化

1.默认配置文件,application/settings/__init__py,代码:

复制代码
class InitConfig():
“”“项目默认初始化配置”""
# 调试模式
DEBUG = True

# 数据库相关配置
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= True
# Redis
REDIS_URL = "redis://@127.0.0.1:6379/0"

复制代码
2.在全局引导文件中, 对redis进行初始化,applicaiton/init.py,代码:

复制代码
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis

from application.utils.config import load_config

创建终端脚本管理对象

manager = Manager()

创建数据库链接对象

db = SQLAlchemy()

redis链接对象 ***

redis = FlaskRedis()

def init_app(config_path):
“”“全局初始化”""

# 创建app应用对象
app = Flask(__name__)
# 项目根目录
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 加载配置
Config = load_config(config_path)
app.config.from_object(Config)

# 数据库初始化
db.init_app(app)
redis.init_app(app) # redis数据库初始化 ***

# 初始化终端脚本工具
manager.app = app

return manager

复制代码
3.session存储到redis数据库中

1.因为需要单独设置一个数据库存放session,所以我们再次单独配置一个关于session加载配置的函数init_session,

application/utils/session.py,代码:

复制代码
from redis import Redis
def init_session(app):
host = app.config.get(“SESSION_REDIS_HOST”,“127.0.0.1”)
port = app.config.get(“SESSION_REDIS_PORT”,6379)
db = app.config.get(“SESSION_REDIS_DB”,0)
print(db)
app.config[“SESSION_REDIS”] = Redis(host=host,port=port,db=db)
复制代码
2.默认配置文件application/settings/init.py中, 添加配置项:

复制代码
class InitConfig():
“”“项目默认初始化配置”""
# 调试模式
DEBUG = True

# 数据库相关配置
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= True
# Redis
REDIS_URL = ""

# 设置密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串 ***
SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw"

'''session存储配置''' ***
# session存储方式配置 ***
SESSION_TYPE = "redis"
# 如果设置session的生命周期是否是会话期, 为True,则关闭浏览器session就失效 ***
SESSION_PERMANENT = False
# 设置session_id在浏览器中的cookie有效期 ***
PERMANENT_SESSION_LIFETIME = 24 * 60 * 60  # session 的有效期,单位是秒 ***
# 是否对发送到浏览器上session的cookie值进行加密 ***
SESSION_USE_SIGNER = True
# 保存到redis的session数的名称前缀 ***
SESSION_KEY_PREFIX = "session:"
# session保存数据到redis时启用的链接对象 ***
SESSION_REDIS = None   # 用于连接redis的配置 ***

SESSION_REDIS_HOST = "127.0.0.1"
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 0

复制代码
3.在本地开发配置中,设置session存储指定的redis库中,application/settings/dev.py,代码:

复制代码
from . import InitConfig
class Config(InitConfig):
“”“项目开发环境下的配置”""
DEBUG = True
# 数据库
SQLALCHEMY_DATABASE_URI = “mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4”
SQLALCHEMY_ECHO = True

# redis ***
REDIS_URL = "redis://@127.0.0.1:6379/0" # 0号redis库用来存redis缓存

# session存储配置 ***
SESSION_REDIS_HOST = "127.0.0.1"
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 1 # 1号redis库用来存session

复制代码
4.在项目全局引导文件application/init.py中对session存储进行初始化,代码:

复制代码
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis
from flask_session import Session

from application.utils.config import load_config
from application.utils.session import init_session

创建终端脚本管理对象

manager = Manager()

创建数据库链接对象

db = SQLAlchemy()

redis链接对象

redis = FlaskRedis()

Session存储对象 ***

session_store = Session()

def init_app(config_path):
“”“全局初始化”""
# 创建app应用对象
app = Flask(name)
# 项目根目录
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))

# 加载配置
Config = load_config(config_path)
app.config.from_object(Config)

# 数据库初始化
db.init_app(app)
redis.init_app(app)

# session存储初始化 ***
init_session(app) # 加载session配置 
session_store.init_app(app) # session存储初始化

# 初始化终端脚本工具
manager.app = app

return manager

复制代码
4.数据迁移初始化

1.项目全局引导文件application/__init__py,代码:

复制代码
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis
from flask_session import Session
from flask_migrate import Migrate,MigrateCommand # ***

from application.utils.config import load_config
from application.utils.session import init_session

创建终端脚本管理对象

manager = Manager()

创建数据库链接对象

db = SQLAlchemy()

redis链接对象

redis = FlaskRedis()

Session存储对象

session_store = Session()

数据迁移实例对象 ***

migrate = Migrate()

def init_app(config_path):
“”“全局初始化”""
# 创建app应用对象
app = Flask(name)
# 项目根目录
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))

# 加载配置
Config = load_config(config_path)
app.config.from_object(Config)

# 数据库初始化 
db.init_app(app)
redis.init_app(app)

# session存储初始化
init_session(app)
session_store.init_app(app)

# 数据迁移初始化 ***
migrate.init_app(app,db)
# 添加数据迁移的命令到终端脚本工具中 ***
manager.add_command('db', MigrateCommand)

# 初始化终端脚本工具
manager.app = app

return manager

复制代码
完成上面的项目构建步骤以后,此时目录结构如下:

复制代码
项目根目录/
├── docs/ # 项目开发文档/接口等备份资料存储目录
├── logs/ # 项目日志存储目录
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prod.py # 生产阶段的配置文件
| | ├ init.py # 项目公共配置文件
| ├── utils/ # 工具函数库/类库
│ │ ├ session.py # session相关的辅助函数
│ │ ├ config.py # 配置相关的辅助函数
│ ├── init.py # 项目初始化文件
└── manage.py # 项目的终端管理脚本文件
复制代码
7.日志初始化

flask中没有内置的日志功能,我们在使用的时候, 一般日志如果不是核心重点,则通过由python内置的logging模块进行配置集成使用即可, 如果项目中日志发挥作用比较重要, 则一般安装部署 ELK日志分析系统.

1.日志的等级

FATAL/CRITICAL = 致命的,危险的
ERROR = 错误
WARNING = 警告
INFO = 信息
DEBUG = 调试
2.构建日志模块

1.把日志初始化相关的代码封装成一个函数,application/utils/logger.py,代码:

复制代码
import logging
from logging.handlers import RotatingFileHandler

class Log():
“”“日志模块”""

def __init__(self, app=None):
    if app is not None:
        self.init_app(app)

def init_app(self,app):
    self.app = app
    return self.setup()

def setup(self):
    """安装日志功能到flask中"""
    # 设置日志的记录等级
    logging.basicConfig(level=self.app.config.get("LOG_LEVEL"))  # 调试debug级

    # 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
    file_log_handler = RotatingFileHandler(
        self.app.BASE_DIR+self.app.config.get("LOG_DIR"),
        maxBytes=self.app.config.get("LOG_MAX_BYTES"),
        backupCount=self.app.config.get("LOG_BACKPU_COUNT")
    )

    # 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
    formatter = logging.Formatter('%(name)s: %(levelname)s %(asctime)s %(filename)s:%(lineno)d %(message)s')
    # 为刚创建的日志记录器设置日志记录格式
    file_log_handler.setFormatter(formatter)

    # 为全局的日志工具对象(flaskapp使用的)添加日志记录器
    logging.getLogger(self.app.config.get("LOG_NAME")).addHandler(file_log_handler)
    # 返回日志器对象提供给业务开发
    logger = logging.getLogger(self.app.config.get("LOG_NAME"))
    return logger

复制代码
2.application/settings/init.py代码:

复制代码
class InitConfig():
“”“项目默认初始化配置”""
# 调试模式
DEBUG = True

# 数据库相关配置
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= True
# Redis
REDIS_URL = ""

# 设置密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串
SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw"

# session存储配置
# session存储方式配置
SESSION_TYPE = "redis"
# 如果设置session的生命周期是否是会话期, 为True,则关闭浏览器session就失效
SESSION_PERMANENT = False
# 设置session_id在浏览器中的cookie有效期
PERMANENT_SESSION_LIFETIME = 24 * 60 * 60  # session 的有效期,单位是秒
# 是否对发送到浏览器上session的cookie值进行加密
SESSION_USE_SIGNER = True
# 保存到redis的session数的名称前缀
SESSION_KEY_PREFIX = "session:"
# session保存数据到redis时启用的链接对象
SESSION_REDIS = None   # 用于连接redis的配置

SESSION_REDIS_HOST = "127.0.0.1"
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 1

# 调整json数据转换中文的配置
JSON_AS_ASCII=False

# 日志相关配置 ***
LOG_LEVEL        = "INFO"              # 日志输出到文件中的最低等级
LOG_DIR          = "logs/0.log"        # 日志存储目录
LOG_MAX_BYTES    = 300 * 1024 * 1024   # 单个日志文件的存储上限[单位: b]
LOG_BACKPU_COUNT = 20                  # 日志文件的最大备份数量
LOG_NAME         = "flask"             # 日志器的名字

复制代码
3.开发环境配置文件dev.py中配置具体的日志相关信息,代码:

复制代码
from . import InitConfig
class Config(InitConfig):
“”“项目开发环境下的配置”""
DEBUG = True
# 数据库
SQLALCHEMY_DATABASE_URI = “mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4”
SQLALCHEMY_ECHO = True

# redis
REDIS_URL = "redis://@127.0.0.1:6379/0"

# session存储配置
SESSION_REDIS_HOST = "127.0.0.1"
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 1

# 日志配置 ***
LOG_LEVEL        = "DEBUG"             # 日志输出到文件中的最低等级
LOG_DIR          = "/logs/mofang.log"  # 日志存储目录
LOG_MAX_BYTES    = 300 * 1024 * 1024   # 单个日志文件的存储上限[单位: b]
LOG_BACKPU_COUNT = 20                  # 日志文件的最大备份数量
LOG_NAME = "mofang"                    # 日志器名称

复制代码
4.在 application/init.py文件中的init_app 方法中调用日志初始化。

复制代码
import os,logging

from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis
from flask_session import Session
from flask_migrate import Migrate,MigrateCommand

from application.utils.config import load_config
from application.utils.session import init_session
from application.utils.logger import Log

创建终端脚本管理对象

manager = Manager()

创建数据库链接对象

db = SQLAlchemy()

redis链接对象

redis = FlaskRedis()

Session存储对象

session_store = Session()

数据迁移实例对象

migrate = Migrate()

日志对象 ***

log = Log()

def init_app(config_path):
“”“全局初始化”""
# 创建app应用对象
app = Flask(name)
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))

# 加载配置
Config = load_config(config_path)
app.config.from_object(Config)

# 数据库初始化
db.init_app(app)
redis.init_app(app)

# session存储初始化
init_session(app)
session_store.init_app(app)

# 数据迁移初始化
migrate.init_app(app,db)
# 添加数据迁移的命令到终端脚本工具中
manager.add_command('db', MigrateCommand)

# 日志初始化 ***
app.log = log.init_app(app)

# 初始化终端脚本工具
manager.app = app

return manager

复制代码
新增日志的项目目录结构如下所示

复制代码
├── application
│ ├── init.py
│ ├── settings
│ │ ├── dev.py
│ │ ├── init.py
│ │ ├── prod.py
│ └── utils
│ ├── config.py
│ ├── init.py
│ ├── logger.py # 日志相关模块代码库
│ └── session.py
├── docs
├── logs # 日志文件存储目录
│ └── mofang.log
└── manage.py
复制代码
经过上面的改造,我们接下来就可以开始创建蓝图了。

8.蓝图初始化

1.通过终端命令创建蓝图,并在蓝图中生成view/model/url等文件

1.在application下创建apps目录,apps以后专门用于保存每一个项目的蓝图,并在apps创建home蓝图目录,并在__init__.py文件中创建蓝图对象

通过自定义终端命令, 创建一个自动生成蓝图目录的命令.application/utils/commands.py,代码:

复制代码
from flask_script import Command, Option

class BlueprintCommand(Command):
“”“蓝图生成命令”""
name = “blue”
option_list = [
Option(’–name’, ‘-n’, dest=‘name’),
]
def run(self, name):
# 生成蓝图名称对象的目录
os.mkdir(name)
open("%s/init.py" % name, “w”)
open("%s/views.py" % name, “w”)
open("%s/models.py" % name, “w”)
with open("%s/urls.py" % name, “w”) as f:
content = “”"from . import views
from application.utils import path
urlpatterns = [

]"""
f.write(content)
print(“蓝图%s创建完成…” % name)
复制代码
2.上面的命令就可以帮我们完成项目中生成蓝图的功能,接下来我们就可以直接把命令注册到manage对象中就可以使用了.

但是, 我们往后的开发中肯定还会继续的需要进行自定义终端命令,所以我们声明一个load_command的函数,让自动帮我们完成加载注册自定义终端命令的过程.

application/utils/commands.py,代码:

复制代码
import os
from importlib import import_module
from flask_script import Command, Option
import inspect

def load_command(manager,command_path=None):
“”“自动加载自定义终端命令”""
if command_path is None:
command_path = “application.utils.commands”

module = import_module(command_path)
class_list = inspect.getmembers(module,inspect.isclass)
for class_item in class_list:
    if issubclass(class_item[1],Command) and class_item[0] != "Command":
        manager.add_command(class_item[1].name,class_item[1])

class BlueprintCommand(Command):
“”“蓝图生成命令”""
name = “blue”
option_list = [
Option(’–name’, ‘-n’, dest=‘name’),
]
def run(self, name):
# 生成蓝图名称对象的目录
os.mkdir(name)
open("%s/init.py" % name, “w”)
open("%s/views.py" % name, “w”)
open("%s/models.py" % name, “w”)
with open("%s/urls.py" % name, “w”) as f:
content = “”"from . import views
from application.utils import path
urlpatterns = [

]"""
f.write(content)
print(“蓝图%s创建完成…” % name)
复制代码
3.在项目全局引导文件application/init.py中, 调用load_command函数注册命令

复制代码
import os,logging

from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis
from flask_session import Session
from flask_migrate import Migrate,MigrateCommand

from application.utils.config import load_config
from application.utils.session import init_session
from application.utils.logger import Log
from application.utils.commands import load_command

创建终端脚本管理对象

manager = Manager()

创建数据库链接对象

db = SQLAlchemy()

redis链接对象

redis = FlaskRedis()

Session存储对象

session_store = Session()

数据迁移实例对象

migrate = Migrate()

日志对象

log = Log()

def init_app(config_path):
“”“全局初始化”""
# 创建app应用对象
app = Flask(name)
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))

# 加载配置
Config = load_config(config_path)
app.config.from_object(Config)

# 数据库初始化
db.init_app(app)
redis.init_app(app)

# session存储初始化
init_session(app)
session_store.init_app(app)

# 数据迁移初始化
migrate.init_app(app,db)
# 添加数据迁移的命令到终端脚本工具中
manager.add_command('db', MigrateCommand)

# 日志初始化
app.log = log.init_app(app)

# 初始化终端脚本工具
manager.app = app

# 注册自定义命令 ***
load_command(manager)

return manager

复制代码
4.接下来就可以在终端下,通过命令生成蓝图目录了.

命令:

cd application/apps
python …/…/manage.py blue -nhome
效果:

2.将蓝图注册到APP应用对象下

有了蓝图以后,接下来我们就可以视图代码,模型代码,路由代码等存储到蓝图目录下了,但是我们需要把蓝图注册到app应用对象下.所以我们注册蓝图这块代码也可以封装到一个函数中.让程序自动识别并注册.

项目中可以有多个蓝图,但是有些蓝图可能并不能提供给客户端访问,所以我们需要在配置文件中声明一个蓝图注册列表, 在init_blueprint函数中只注册配置列表的蓝图

1.application/settings/init.py,代码:

复制代码
class InitConfig():
“”“项目默认初始化配置”""
# 调试模式
DEBUG = True

# 数据库相关配置
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= True
# Redis
REDIS_URL = ""

# 设置密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串
SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw"

# session存储配置
# session存储方式配置
SESSION_TYPE = "redis"
# 如果设置session的生命周期是否是会话期, 为True,则关闭浏览器session就失效
SESSION_PERMANENT = False
# 设置session_id在浏览器中的cookie有效期
PERMANENT_SESSION_LIFETIME = 24 * 60 * 60  # session 的有效期,单位是秒
# 是否对发送到浏览器上session的cookie值进行加密
SESSION_USE_SIGNER = True
# 保存到redis的session数的名称前缀
SESSION_KEY_PREFIX = "session:"
# session保存数据到redis时启用的链接对象
SESSION_REDIS = None   # 用于连接redis的配置

SESSION_REDIS_HOST = "127.0.0.1"
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 1

# 调整json数据转换中文的配置
JSON_AS_ASCII=False

# 日志相关配置
LOG_LEVEL        = "INFO"              # 日志输出到文件中的最低等级
LOG_DIR          = "logs/0.log"        # 日志存储目录
LOG_MAX_BYTES    = 300 * 1024 * 1024   # 单个日志文件的存储上限[单位: b]
LOG_BACKPU_COUNT = 20                  # 日志文件的最大备份数量
LOG_NAME         = "flask"             # 日志器的名字

# 蓝图注册列表 ***
INSTALLED_APPS = [

]

复制代码
application/settings/dev.py,代码:

复制代码
from . import InitConfig
class Config(InitConfig):
“”“项目开发环境下的配置”""
DEBUG = True
# 数据库
SQLALCHEMY_DATABASE_URI = “mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4”
SQLALCHEMY_ECHO = True

# redis
REDIS_URL = "redis://@127.0.0.1:6379/0"

# session存储配置
SESSION_REDIS_HOST = "127.0.0.1"
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 1

# 日志配置
LOG_LEVEL        = "DEBUG"             # 日志输出到文件中的最低等级
LOG_DIR          = "/logs/mofang.log"  # 日志存储目录
LOG_MAX_BYTES    = 300 * 1024 * 1024   # 单个日志文件的存储上限[单位: b]
LOG_BACKPU_COUNT = 20                  # 日志文件的最大备份数量
LOG_NAME = "mofang"                    # 日志器名称

# 注册蓝图  ***
INSTALLED_APPS = [ 
    "application.apps.home",
]

复制代码
2.在init_blueprint函数中,针对注册的蓝图列表注册到app应用对象里面,

application/utils/init.py,代码:

复制代码
def init_blueprint(app):
“”“自动注册蓝图”""
blueprint_path_list = app.config.get(“INSTALLED_APPS”)
for blueprint_path in blueprint_path_list:
blueprint_name = blueprint_path.split(".")[-1]
# 自动创建蓝图对象
blueprint = Blueprint(blueprint_name,blueprint_path)

    # 注册蓝图对象到app应用对象中
    app.register_blueprint(blueprint,url_prefix="")

复制代码
3.项目全局引导文件中, 调用init_blueprint方法, 自动注册蓝图.application/init.py,代码:

复制代码
import os,logging

from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis
from flask_session import Session
from flask_migrate import Migrate,MigrateCommand

from application.utils import init_blueprint
from application.utils.config import load_config
from application.utils.session import init_session
from application.utils.logger import Log
from application.utils.commands import load_command

创建终端脚本管理对象

manager = Manager()

创建数据库链接对象

db = SQLAlchemy()

redis链接对象

redis = FlaskRedis()

Session存储对象

session_store = Session()

数据迁移实例对象

migrate = Migrate()

日志对象

log = Log()

def init_app(config_path):
“”“全局初始化”""
# 创建app应用对象
app = Flask(name)
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))

# 加载配置
Config = load_config(config_path)
app.config.from_object(Config)

# 数据库初始化
db.init_app(app)
redis.init_app(app)

# session存储初始化
init_session(app)
session_store.init_app(app)

# 数据迁移初始化
migrate.init_app(app,db)
# 添加数据迁移的命令到终端脚本工具中
manager.add_command('db', MigrateCommand)

# 日志初始化
app.log = log.init_app(app)

# 蓝图注册 ***
init_blueprint(app)

# 初始化终端脚本工具
manager.app = app

# 注册自定义命令
load_command(manager)

return manager

复制代码
3.注册路由和视图之间的关系

1.注册子路由和视图之间的关系

注册了蓝图对象以后,蓝图下面的视图方法和视图对应的路由关系也要进行注册!

所以, 在蓝图home下面的urls.py文件中,通过path方法把url地址和视图方法进行处理成字典,然后把字典作为成员返回到变量urlpatterns列表中.

1.application/utils/init.py,生成path函数,代码:

from flask import Blueprint
from importlib import import_module
def path(rule,func_view):
# 把蓝图下视图和路由之间的映射关系处理成字典结构,方便后面注册蓝图的时候,直接传参
return {“rule”:rule,“view_func”:func_view}
2.在蓝图下的urls.py中,注册视图和路由的关系,home/urls.py,代码:

from . import views
from application.utils import path
urlpatterns = [
path("/",views.index),
]
视图代码:

def index():
return ‘index’
3.在init_blueprint初始化蓝图的函数中, 生成蓝图对象以后自动加载并注册蓝图和视图

application/utils/init.py,代码:

复制代码
from flask import Blueprint
from importlib import import_module
def path(rule,func_view):
# 把蓝图下视图和路由之间的映射关系处理成字典结构,方便后面注册蓝图的时候,直接传参
return {“rule”:rule,“view_func”:func_view}

def init_blueprint(app):
“”“自动注册蓝图”""
blueprint_path_list = app.config.get(“INSTALLED_APPS”)
for blueprint_path in blueprint_path_list:
blueprint_name = blueprint_path.split(".")[-1]
# 自动创建蓝图对象
blueprint = Blueprint(blueprint_name,blueprint_path)
# 蓝图自动注册和绑定视图和子路由
url_module = import_module(blueprint_path+".urls") # 加载蓝图下的子路由文件
for url in url_module.urlpatterns: # 遍历子路由中的所有路由关系
blueprint.add_url_rule(**url) # 注册到蓝图下
# 注册蓝图对象到app应用对象中
app.register_blueprint(blueprint,url_prefix="")
复制代码
2.注册总路由和蓝图之间的关系

4.此时, 运行项目,就允许蓝图中视图通过url地址提供给客户端访问了.

上面蓝图注册到app时, 没有设置url_prefix路由前缀, 接下来我们可以单独设置一个总路由application/urls.py,进行路由前缀的设置.

在项目默认配置文件中,application/settings/init.py,新增总路由的配置项

复制代码
class InitConfig():
“”“项目默认初始化配置”""
# 调试模式
DEBUG = True

# 数据库相关配置
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= True
# Redis
REDIS_URL = ""

# 设置密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串
SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw"

# session存储配置
# session存储方式配置
SESSION_TYPE = "redis"
# 如果设置session的生命周期是否是会话期, 为True,则关闭浏览器session就失效
SESSION_PERMANENT = False
# 设置session_id在浏览器中的cookie有效期
PERMANENT_SESSION_LIFETIME = 24 * 60 * 60  # session 的有效期,单位是秒
# 是否对发送到浏览器上session的cookie值进行加密
SESSION_USE_SIGNER = True
# 保存到redis的session数的名称前缀
SESSION_KEY_PREFIX = "session:"
# session保存数据到redis时启用的链接对象
SESSION_REDIS = None   # 用于连接redis的配置

SESSION_REDIS_HOST = "127.0.0.1"
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 1

# 调整json数据转换中文的配置
JSON_AS_ASCII=False

# 日志相关配置
LOG_LEVEL        = "INFO"              # 日志输出到文件中的最低等级
LOG_DIR          = "logs/0.log"        # 日志存储目录
LOG_MAX_BYTES    = 300 * 1024 * 1024   # 单个日志文件的存储上限[单位: b]
LOG_BACKPU_COUNT = 20                  # 日志文件的最大备份数量
LOG_NAME         = "flask"             # 日志器的名字

# 蓝图注册列表
INSTALLED_APPS = [

]


# 总路由 ***
URL_PATH = "application.urls"

复制代码
5.创建总路由文件并注册蓝图和路由前缀的关系, application/urls.py,代码:

from application.utils import include
urlpatterns = [
include("",“home.urls”),
]
6.接下来,在init_blueprint蓝图初始化函数中新增判断识别路由前缀的代码; 同时, 把路由前缀和蓝图映射关系的处理代码封装成include方法,方便以后需求变化时可以直接调整.

application/utils/init.py,代码:

复制代码
from flask import Blueprint
from importlib import import_module
def path(rule,func_view):
# 把蓝图下视图和路由之间的映射关系处理成字典结构,方便后面注册蓝图的时候,直接传参
return {“rule”:rule,“view_func”:func_view}

def include(url_prefix, blueprint_path):
“”“把路由前缀和蓝图进行关系映射”""
return {“url_prefix”:url_prefix,“blueprint_path”:blueprint_path}

def init_blueprint(app):
“”“自动注册蓝图”""
blueprint_path_list = app.config.get(“INSTALLED_APPS”)
for blueprint_path in blueprint_path_list:
blueprint_name = blueprint_path.split(".")[-1]
# 自动创建蓝图对象
blueprint = Blueprint(blueprint_name,blueprint_path)
# 蓝图自动注册和绑定视图和子路由
url_module = import_module(blueprint_path+".urls") # 加载蓝图下的子路由文件
for url in url_module.urlpatterns: # 遍历子路由中的所有路由关系
blueprint.add_url_rule(**url) # 注册到蓝图下

    # 读取总路由文件
    url_path = app.config.get("URL_PATH")
    urlpatterns = import_module(url_path).urlpatterns  # 加载蓝图下的子路由文件
    url_prefix = "" # 蓝图路由前缀
    for urlpattern in urlpatterns:
        if urlpattern["blueprint_path"] == blueprint_name+".urls":
            url_prefix = urlpattern["url_prefix"]
            break
    # 注册蓝图对象到app应用对象中,  url_prefix 蓝图的路由前缀
    app.register_blueprint(blueprint,url_prefix=url_prefix)

复制代码
4.自动注册蓝图下的所有模型

1.在蓝图下的models.py中声明模型,例如:

复制代码
from application import db
class User(db.Model):
tablename = “mf_user”
id = db.Column(db.Integer, primary_key=True, comment=“主键ID”)
name = db.Column(db.String(255), unique=True, comment=“账户名”)
password = db.Column(db.String(255), comment=“登录密码”)
ip_address = db.Column(db.String(255), index=True, comment=“登录IP”)

def __repr__(self):
    return self.name

复制代码
2.然后在终端下执行数据迁移

cd …/…
python manage.py db init
python manage.py db migrate -m “text”
3.上面的命令执行以后, 我们可以发现模型根本被flask进行识别到.所以我们需要把模型注册到flask项目中.

application/utils/init.py,代码:

复制代码
from flask import Blueprint
from importlib import import_module
def path(rule,func_view):
# 把蓝图下视图和路由之间的映射关系处理成字典结构,方便后面注册蓝图的时候,直接传参
return {“rule”:rule,“view_func”:func_view}

def include(url_prefix, blueprint_path):
“”“把路由前缀和蓝图进行关系映射”""
return {“url_prefix”:url_prefix,“blueprint_path”:blueprint_path}

def init_blueprint(app):
“”“自动注册蓝图”""
blueprint_path_list = app.config.get(“INSTALLED_APPS”)
for blueprint_path in blueprint_path_list:
blueprint_name = blueprint_path.split(".")[-1]
# 自动创建蓝图对象
blueprint = Blueprint(blueprint_name,blueprint_path)
# 蓝图自动注册和绑定视图和子路由
url_module = import_module(blueprint_path+".urls") # 加载蓝图下的子路由文件
for url in url_module.urlpatterns: # 遍历子路由中的所有路由关系
blueprint.add_url_rule(**url) # 注册到蓝图下

    # 读取总路由文件
    url_path = app.config.get("URL_PATH")
    urlpatterns = import_module(url_path).urlpatterns  # 加载蓝图下的子路由文件
    url_prefix = "" # 蓝图路由前缀
    for urlpattern in urlpatterns:
        if urlpattern["blueprint_path"] == blueprint_name+".urls":
            url_prefix = urlpattern["url_prefix"]
            break

    # 注册模型 ***
    import_module(blueprint_path+".models")

    # 注册蓝图对象到app应用对象中,  url_prefix 蓝图的路由前缀
    app.register_blueprint(blueprint,url_prefix=url_prefix)

复制代码
项目能自动加载总路由和蓝图路由以后的项目目录结构,如下:

复制代码
项目根目录/
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ init.py # 项目默认初始化配置文件
│ │ ├ dev.py # 开发阶段的配置文件
│ │ └ prod.py # 生产阶段的配置文件
│ ├── init.py # 项目初始化全局引导文件
| ├── utils/ # 项目工具类库目录
│ │ ├ commands.py # 自定义命令和加载命令的相关函数
│ │ ├ config.py # 项目配置加载的辅助函数
│ │ ├ session.py # 项目存储session相关的函数
│ │ └ logger.py # 日志模块
│ ├── apps/ # 保存项目中所有蓝图的存储目录
│ │ ├── home # 蓝图目录【这里是举例而已】
│ │ │ ├── init.py # 蓝图的初始化文件
│ │ │ ├── urls.py # 蓝图的子路由文件
│ │ │ ├── models.py # 蓝图的模型文件
│ │ │ └── views.py # 蓝图的视图文件
│ │ ├── init.py
│ └── urls.py # 总路由
├── manage.py # 项目的终端管理脚本文件
复制代码

分类: Python全栈31期-笔记
标签: PythonS31-笔记
好文要顶 关注我 收藏该文
iR-Poke
关注 - 4
粉丝 - 7
+加关注
0 0
« 上一篇: day97:MoFang:移动端APP开发准备&移动端项目搭建&APICloud前端框架
posted @ 2020-11-26 22:33 iR-Poke 阅读(40) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
博客园派送云上免费午餐,AWS注册立享12个月免费套餐
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】阿里云钜惠返场,奖励继续赢5万现金,错过再等一年
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【福利】AWS携手博客园为开发者送免费套餐与抵扣券

相关博文:
· Day98数据分析(一)
· ArrayList实现原理(JDK1.8)
· 十分钟掌握Pandas(上)——来自官网API
· Java并发之synchronized关键字和Lock接口
· Aso.NetCore的配置系统Configuration
» 更多推荐…
AWS免费套餐
最新 IT 新闻:
· 一文速览SpaceX首次载人商业发射 四名宇航员在太空生活半年
· 任正非:华为和荣耀不要藕断丝连 荣耀要做华为最强的竞争对手
· 复活有望!力帆重整计划草案获通过
· 中国降价海外疯涨!特斯拉全系欧洲多国大涨价 最高涨3.9万
· 悬崖边的傅盛,看猎豹坠落
» 更多新闻…
公告
昵称: iR-Poke
园龄: 1年3个月
粉丝: 7
关注: 4
+加关注
搜索

找找看
我的标签
PythonS31-笔记(94)
PythonS31-小程序(4)
PythonS31-周测错题(1)
Python31-面试题(1)
积分与排名
积分 - 6594
排名 - 105756
随笔分类
Python31-面试题(2)
Python全栈31期-笔记(94)
随笔档案
2020年11月(19)
2020年10月(17)
2020年9月(19)
2020年8月(24)
2020年7月(20)
2020年6月(2)
阅读排行榜

  1. 小程序5:FTP程序(343)
  2. day69:Vue:组件化开发&Vue-Router&Vue-client(179)
  3. day43:CSS样式相关(163)
  4. day21:正则函数&模块和包(import)(145)
  5. day53:django:URL别名/反向解析&URL分发&命名空间&ORM多表操作修改/查询(140)
    Copyright © 2020 iR-Poke
    Powered by .NET 5.0.0 on Kubernetes
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值