当一个模块包含太多代码时,常用做法是将模块升级为包,然后把原模块的内容按照类型分离成不同模块,不同模块在通过一定技巧组合起来
- 当视图模块内容太多时,可以使用蓝图(blueprients)可以把views.py模块升级为蓝图子包,views.py的内置在按照不同内容分为不同模块如blog.py,admin.py等
使用包组织项目代码
- Flask对项目的组织方式没有固定要求。对于小型项目完全可以都放在主模块里。 随着项目越来越大, 更好的方式是将单一的模块升级为包(Package),把不同部分的代码分模块存放(各类代码安装类别存储在对应的模块中)。
- 模块:一个有效的python文件(.py)即是一个模块
- 包:每一个包含init_.py的文件夹即成为包, init__.py文件通过被称为构造文件,文件内容可以为空也可以用来放初始化代码。 当包或包内的模块被导入时,构造文件将自动执行。 包的名称通常使用程序名
Flask配置组织形式
方式1: 环境变量
.env .flaskenv
定义在.env, .flaskenv中。
通过config对象直接写入
单独的py文件
一般命名setting.py或config.py。 以键值对的方式写出配置。在需要使用的地方app.config.from_pyfile导入
app.config.from_pyfile(‘config.py’)
使用类组织配置
在单个配置文件中使用python类来组织多个不同类别的配置。
import os
basedir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
class BaseConfig(object):
SECRET_KEY = '2432trfdsfgdsfsdf'
class DevelopmentConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'myblog.sqlite')
class TestingConfig(BaseConfig):
TESTING = True
class ProductionConfig(BaseConfig):
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URI', 'sqlite:///' + os.path.join(basedir, 'myblog.sqlite'))
config = {
'development': DevelopmentConfig,
'testing' : TestingConfig,
'production': ProductionConfig
}
创建实例程序后使用app.config_from_object()方法加载配置,传入配置类
app = Flask('myblog')
config_name = os.getenv('FLASK_CONFIG', 'development')
app.config.from_object(config[config_name])
方式2:实例文件夹覆盖
实例文件夹(instance folder)
- 在项目根目录(程序旁边)创建一个名称为instance的文件夹,存储开发或部署时的配置文件。 一般放铭感信息
- Flask允许多次加载配置,使用instance文件夹中的配置覆盖通用配置。
app = Flask(__name__, instance_relative_config=True) #通过instance_relative_config=True,告诉Flask配置文件路径时相对于实例文件夹的(默认是相对实例跟目录)
app.config.from_object('config') #通用配置
app.config.from_pyfile('config.py') #instance文件夹下配置
instance文件夹路径可以通过app.instance_path获取,可以用于存放临时文件如数据库
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(app.instance_path, 'database.sqlite')
使用蓝本组织项目
实例化蓝本:使用Flask提供的Blueprient类可以创建蓝本实例,
- 可以为蓝本实例注册路由、错误处理函数、上下文处理函数、请求处理函数、单独的静态文件夹和模板文件夹。
- 蓝本实例及一些列注册在这个蓝本实例上的操作被成为一个蓝本。
1 在子包或模块里创建蓝本并装配蓝本内容(使用子包管理蓝本可以设置蓝本独有的静态文件和模板)
2 注册蓝本:把蓝本注册到程序实例上才可以发挥作用
from flask import Blueprient
admin_bp = Blueprient('admin', __name__) #实例化,第一个参数为蓝本名称 蓝本对象名称习惯加BP方便区分,非必须
#2
@admin_bp.route('/login')
def login():
pass
# 错误处理
#使用蓝本实例的errorhander()装饰器可以错误处理器注册到蓝本上,只会捕捉访问这个蓝本的错误; 使用app.errorhander()装饰器可以注册一个全局的错误处理器。
# 请求处理
# 在蓝本中使用before_request, after_request, teardown_request等装饰器处理当前蓝本的请求。
# 可以使用before_app_request,after_app_reuqest, teardown_app_request, before_first_app_request方法注册全局的
# 模板上下文
#使用context_processor注册蓝本上下文, 使用context_app_processoer注册全局上下文处理器。
# 蓝本对象也可以使用app_template_global(), app_template_tilter(), app_template_test()装饰器分别来注册全局的模板全局函数、模板过滤器、模板测试器。
2 注册蓝本
from blog.blueprients.admin import admin_bp
app.register_bluprient(admin_bp, url_prefix='/admin') # 蓝本使用Flask.register_blueprient()方法注册,必须传入的参数是前面注册的蓝本实例名称,其他参数用来控制蓝本行为
#如ulr_prefix为蓝本下所有视图URL附加一个URL前缀。
# 如subdomain参数可以为蓝本下的路由设置子域名。
app.register_bluprient(blog_bp)
app.register_bluprient(user_bp, subdomain='user')
- 使用蓝本可以将程序模块化(modular),一个程序可以注册多个蓝本。
蓝本的端点路由
默认”蓝本名.视图函数名”。 如:{{ url_for(‘admin.index’) }}
蓝本资源
如果不同蓝本资源样式不同,可以为不同蓝本定义独有的静态文件和模板。
- 这时需要把蓝本模块升级为包。 在构造文件中创建蓝本实例,在蓝本包中创建静态文件夹static和模板文件夹templates。
- 在蓝本中定义静态文件和模板文件夹
admin_bp = Blueprient('admin', __name__, static_folder='static', static_url_path='/admin/static') #如果注册蓝本定义了URL前缀则可以不设置static_url_path,会自动默认为'/蓝本前缀/static'
#获取静态资源时使用{{ url_for('admin.static', filename='...') }}
#当蓝本包含独有的摹本文件时
admin_bp= Blueprient('admin', __name__, template_folder='templates') #Flask会优先从全局模板文件夹中寻找,如果没找到再去蓝本所在模板文件夹查找。
使用工厂函数创建程序实例
在OOP(Object-Oriented Programming面向对象编程)中,工厂(factory)是指创建其他对象的对象。
- Flask中,使用工厂函数创建返回实例app,工厂函数一般命名未create_app()。 使用它可以在任何地方创建程序实例。 工厂函数接收配置名作为参数,返回创建好的程序实例。
- 使用工厂函数后不必将配置写死在某处,可以在不同地方跟着需要的配置创建实例。
- 借助工厂函数,可以分离扩展的初始化操作, 进而减少循环依赖的发生。
import os
from flask import Flask
from flask import Blueprint
from myblog.config import config
from myblog.extensions import db #在单独地方初始化扩展
def create_app(config_name=None): #1 在工厂函数加载配置
if config_name is None:
config_name = os.getenv('FLASK_CONFIG', 'development')
app = Flask('myblog')
app.config.from_object(config[config_name])
register_extensions(app) #开始组织工厂函数
register_blueprints(app) # 结束...
return app
def register_extensions(app):
db.init_app(app)
def register_blueprints(app):
from blueprients.forntend import forntend_bp
from blueprients.admin import admin_bp
app.register_blueprint(forntend_bp)
app.register_blueprint(admin_bp, url_prefix='/admin')
# 启动程序 flask run
# 使用flask run时, flask还会自动从Flask_APP的对应的模块寻找名为create_app()或make_app()的工厂函数,自动调用工厂函数创建实例运行。
# current_app 工厂函数创建的不同实例配置不同, 使用current_app对当前实例进行操作
部署
使用gunicorn运行程序
安装: pip install gunicorn
启动:运行一个程序:
$ gunicorn [OPTIONS] 模块名: 变量名 #模块名即包含程序实例的模块,一般为wsgi.py,文件内包含创建的app$ gunicorn --workers=4 wsgi:app
#简写
查询
首先执行如下命令获取Gunicorn进程树:
pstree -ap|grep gunicorn
关闭
首先执行如下命令获取Gunicorn进程树:
pstree -ap|grep gunicorn
之后输入如下指令关闭进程:
kill -9 pid
使用supervisor
https://blog.csdn.net/donggege214/article/details/80264811
安装: yum install supervisor //改用pip安装
启动: service supervisord start
https://segmentfault.com/a/1190000020187018
supervisor支持venv http://www.mamicode.com/info-detail-2308922.html; https://blog.csdn.net/weixin_45063926/article/details/105770804