目录

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 # 项目的终端管理脚本文件

day98:MoFang:服务端项目搭建的更多相关文章

  1. day97:MoFang:移动端APP开发准备&移动端项目搭建&APICloud前端框架

    目录 1.移动端开发相关概念 1.APP类型 2.移动端屏幕介绍 3.移动端自适配方案 4.元信息(meta) 2.APP开发准备 1.注册APPCLoud账号 2.下载APP开发编辑器 3.下载AP ...

  2. spring-oauth-server实践:客户端和服务端环境搭建

    客户端:http://localhost:8080/spring-oauth-client/index.jsp 服务端:http://localhost:8080/spring-oauth-serve ...

  3. 如何实现从Java入门到服务端项目开发的进阶?

    对于打算入门或者刚刚入门学习Java的人来说,刚开始接触这门学科,往往会觉得不知所措,也会觉得很迷茫.结合前人经验,就从入门到进阶对于Java的学习而言,应该对于学习时间.目标和内容规划有一个清晰的定 ...

  4. Vue+koa2开发一款全栈小程序(5.服务端环境搭建和项目初始化)

    1.微信公众平台小程序关联腾讯云 腾讯云的开发环境是给免费的一个后台,但是只能够用于开发,如果用于生产是需要花钱的,我们先用开发环境吧 1.用小程序开发邮箱账号登录微信公众平台 2.[设置]→[开发者 ...

  5. Redis服务端的搭建(初级)

    前方低能,仅适合入门级菜鸟阅读,大神大牛通通闪开! 前言:redis经常被用来做缓存(原因自行科普),基于学习的需要自己搭建了一个redis服务器,考虑到项目的分布式部署,所以前期开始的时候,redi ...

  6. Node服务端极速搭建 - nvmhome

    本文意在让你掌握极速搭建Node服务端(任何Project) $ whoami name: kelvin email: kelvv@outlook.com homepage: www.kelvv.co ...

  7. Node服务端极速搭建 -- nvmhome

    > 本文意在让你掌握极速搭建Node服务端(任何Project) ```$ whoaminame: kelvinemail: kelvv@outlook.comhomepage: www.kel ...

  8. Android中直播视频技术探究之---视频直播服务端环境搭建(Nginx+RTMP)

    一.前言 前面介绍了Android中视频直播中的一个重要类ByteBuffer,不了解的同学可以 点击查看 到这里开始,我们开始动手开发了,因为我们后续肯定是需要直播视频功能,然后把视频推流到服务端, ...

  9. Netty入门一:服务端应用搭建 & 启动过程源码分析

    最近周末也没啥事就学学Netty,同时打算写一些博客记录一下(写的过程理解更加深刻了) 本文主要从三个方法来呈现:Netty核心组件简介.Netty服务端创建.Netty启动过程源码分析 如果你对Ne ...

随机推荐

  1. 一站式Web开发套件BeetleX.WebFamily

    BeetleX.WebFamily是一款前后端分离的Web开发套件,但它并不依赖于nodejs/npm/webpack等相关工具:而使用自身实现的方式来完成前后端分离的Web应用开发:套件以组件的方式 ...

  2. CodeForces 1327F AND Segments

    题意 给三个整数 \(n,k,m\) 和 \(m\) 个限制 \((l_i,r_i,x_i)\),求有多少个长度为 \(n\) 的序列 \(a\) 满足: 对于 \(1\leq i\leq n\) 有 ...

  3. 合适的LoRa网关应该怎么选择

    LoRa网关是什么 LoRa网关有时也被称之为lora基站或者lora集中器,它在lora星形组网中处于核心位置,是数据终端和服务器之间的一个信息桥梁.LoRa网关使用的是不同扩频因子,因为不同的扩频 ...

  4. 公钥、私钥、SSL/TLS、会话密钥、DES

    一,公钥私钥 1,公钥和私钥成对出现 2,公开的密钥叫公钥,只有自己知道的叫私钥 3,用公钥加密的数据只有对应的私钥可以解密 4,用私钥加密的数据只有对应的公钥可以解密 5,如果可以用公钥解密,则必然 ...

  5. JNI-Thread中start方法的调用与run方法的回调分析

    前言 在java编程中,线程Thread是我们经常使用的类.那么创建一个Thread的本质究竟是什么,本文就此问题作一个探索. 内容主要分为以下几个部分 1.JNI机制的使用 2.Thread创建线程 ...

  6. 【Android Studio】安卓开发初体验1——安装与试用

    安装 (安装预留硬盘(C盘)空余空间16G以上,8G以上内存) Intel用户: 安装Android Studio和AVD(安卓虚拟机 Android Virtual Device) 安装过程需要注意 ...

  7. python爬虫01在Chrome浏览器抓包

    尽量不要用国产浏览器,很多是有后门的 chrome是首选 百度 按下F12 element标签下对应的HTML代码 点击Network,可以看到很多请求 HTTP请求的方式有好几种,GET,POST, ...

  8. 【有奖众测】给HMS Core文档提建议,赢大奖华为Watch!

    为了提升HMS Core开发者的文档体验,提升开发效率,邀请所有开发者体验HMS Core文档,并贡献您的建议. 无论是文档让您困惑的地方,还是您发现的问题,或者您觉得可以做的更好的地方,都可以尽情的 ...

  9. reids 入门

    1.reids 服务的安装有两种 1.1 exe文件安装,安装完成后,就直接在 "服务"列表中可以查看,并可以停止或启动 1.2 命令行安装:将文件解压至指定文件夹,CMD命令进入 ...

  10. read/write系统调用

    /*拷贝文件内容实例read系统调用.write系统调用ssize_t read(int fd, void *buf, size_t count);ssize_t write(int fd, cons ...