当一个模块包含太多代码时,常用做法是将模块升级为包,然后把原模块的内容按照类型分离成不同模块,不同模块在通过一定技巧组合起来

  • 当视图模块内容太多时,可以使用蓝图(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类来组织多个不同类别的配置。

  1. import os
  2. basedir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
  3. class BaseConfig(object):
  4. SECRET_KEY = '2432trfdsfgdsfsdf'
  5. class DevelopmentConfig(BaseConfig):
  6. SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'myblog.sqlite')
  7. class TestingConfig(BaseConfig):
  8. TESTING = True
  9. class ProductionConfig(BaseConfig):
  10. SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URI', 'sqlite:///' + os.path.join(basedir, 'myblog.sqlite'))
  11. config = {
  12. 'development': DevelopmentConfig,
  13. 'testing' : TestingConfig,
  14. 'production': ProductionConfig
  15. }

创建实例程序后使用app.config_from_object()方法加载配置,传入配置类

  1. app = Flask('myblog')
  2. config_name = os.getenv('FLASK_CONFIG', 'development')
  3. app.config.from_object(config[config_name])

方式2:实例文件夹覆盖

实例文件夹(instance folder)

  • 在项目根目录(程序旁边)创建一个名称为instance的文件夹,存储开发或部署时的配置文件。 一般放铭感信息
  • Flask允许多次加载配置,使用instance文件夹中的配置覆盖通用配置。
  1. app = Flask(__name__, instance_relative_config=True) #通过instance_relative_config=True,告诉Flask配置文件路径时相对于实例文件夹的(默认是相对实例跟目录)
  2. app.config.from_object('config') #通用配置
  3. app.config.from_pyfile('config.py') #instance文件夹下配置

instance文件夹路径可以通过app.instance_path获取,可以用于存放临时文件如数据库

  1. SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(app.instance_path, 'database.sqlite')

使用蓝本组织项目

实例化蓝本:使用Flask提供的Blueprient类可以创建蓝本实例,

  • 可以为蓝本实例注册路由、错误处理函数、上下文处理函数、请求处理函数、单独的静态文件夹和模板文件夹。
  • 蓝本实例及一些列注册在这个蓝本实例上的操作被成为一个蓝本。

1 在子包或模块里创建蓝本并装配蓝本内容(使用子包管理蓝本可以设置蓝本独有的静态文件和模板)
2 注册蓝本:把蓝本注册到程序实例上才可以发挥作用

  1. from flask import Blueprient
  2. admin_bp = Blueprient('admin', __name__) #实例化,第一个参数为蓝本名称 蓝本对象名称习惯加BP方便区分,非必须
  3. #2
  4. @admin_bp.route('/login')
  5. def login():
  6. pass
  7. # 错误处理
  8. #使用蓝本实例的errorhander()装饰器可以错误处理器注册到蓝本上,只会捕捉访问这个蓝本的错误; 使用app.errorhander()装饰器可以注册一个全局的错误处理器。
  9. # 请求处理
  10. # 在蓝本中使用before_request, after_request, teardown_request等装饰器处理当前蓝本的请求。
  11. # 可以使用before_app_request,after_app_reuqest, teardown_app_request, before_first_app_request方法注册全局的
  12. # 模板上下文
  13. #使用context_processor注册蓝本上下文, 使用context_app_processoer注册全局上下文处理器。
  14. # 蓝本对象也可以使用app_template_global(), app_template_tilter(), app_template_test()装饰器分别来注册全局的模板全局函数、模板过滤器、模板测试器。

2 注册蓝本

  1. from blog.blueprients.admin import admin_bp
  2. app.register_bluprient(admin_bp, url_prefix='/admin') # 蓝本使用Flask.register_blueprient()方法注册,必须传入的参数是前面注册的蓝本实例名称,其他参数用来控制蓝本行为
  3. #如ulr_prefix为蓝本下所有视图URL附加一个URL前缀。
  4. # 如subdomain参数可以为蓝本下的路由设置子域名。
  5. app.register_bluprient(blog_bp)
  6. app.register_bluprient(user_bp, subdomain='user')
  • 使用蓝本可以将程序模块化(modular),一个程序可以注册多个蓝本。

蓝本的端点路由

默认”蓝本名.视图函数名”。 如:{{ url_for(‘admin.index’) }}

蓝本资源

如果不同蓝本资源样式不同,可以为不同蓝本定义独有的静态文件和模板。

  • 这时需要把蓝本模块升级为包。 在构造文件中创建蓝本实例,在蓝本包中创建静态文件夹static和模板文件夹templates。
  • 在蓝本中定义静态文件和模板文件夹
  1. admin_bp = Blueprient('admin', __name__, static_folder='static', static_url_path='/admin/static') #如果注册蓝本定义了URL前缀则可以不设置static_url_path,会自动默认为'/蓝本前缀/static'
  2. #获取静态资源时使用{{ url_for('admin.static', filename='...') }}
  3. #当蓝本包含独有的摹本文件时
  4. admin_bp= Blueprient('admin', __name__, template_folder='templates') #Flask会优先从全局模板文件夹中寻找,如果没找到再去蓝本所在模板文件夹查找。

使用工厂函数创建程序实例

在OOP(Object-Oriented Programming面向对象编程)中,工厂(factory)是指创建其他对象的对象。

  • Flask中,使用工厂函数创建返回实例app,工厂函数一般命名未create_app()。 使用它可以在任何地方创建程序实例。 工厂函数接收配置名作为参数,返回创建好的程序实例。
  • 使用工厂函数后不必将配置写死在某处,可以在不同地方跟着需要的配置创建实例。
  • 借助工厂函数,可以分离扩展的初始化操作, 进而减少循环依赖的发生。


  1. import os
  2. from flask import Flask
  3. from flask import Blueprint
  4. from myblog.config import config
  5. from myblog.extensions import db #在单独地方初始化扩展
  6. def create_app(config_name=None): #1 在工厂函数加载配置
  7. if config_name is None:
  8. config_name = os.getenv('FLASK_CONFIG', 'development')
  9. app = Flask('myblog')
  10. app.config.from_object(config[config_name])
  11. register_extensions(app) #开始组织工厂函数
  12. register_blueprints(app) # 结束...
  13. return app
  14. def register_extensions(app):
  15. db.init_app(app)
  16. def register_blueprints(app):
  17. from blueprients.forntend import forntend_bp
  18. from blueprients.admin import admin_bp
  19. app.register_blueprint(forntend_bp)
  20. app.register_blueprint(admin_bp, url_prefix='/admin')
  21. # 启动程序 flask run
  22. # 使用flask run时, flask还会自动从Flask_APP的对应的模块寻找名为create_app()或make_app()的工厂函数,自动调用工厂函数创建实例运行。
  23. # 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