目录
1.通过终端命令创建蓝图,并在蓝图中生成view/model/url等文件
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:[email protected]: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:[email protected]: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:[email protected]: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:[email protected]: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 # 项目的终端管理脚本文件