我对使用flask不熟悉,因此我进行了大量研究,以找出构建应用程序的最佳方法。我一直在关注应用程序工厂并使用蓝图,但是在弄清楚如何使用应用程序范围的库并保持应用程序上下文时遇到麻烦。例如,这是我的应用程序结构:
├── app
│ ├── acuity
│ │ ├── handlers.py
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── config.py
│ ├── __init__.py
│ ├── logs
│ ├── main
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── slackapi.py
│ └── templates
│ └── acuity
│ └── acuity_slack.j2
├── gunicorn_config.py
├── slackbot.py
├── README.md
└── requirements.txt
Main和Acuity是蓝图。 Main不执行任何操作,唯一的终点是敏锐度。在acuity.handlers中,我要导入app.slackapi,但无论如何切片都不能使用current_app。我需要使用应用程序上下文才能访问日志记录和配置变量。
将slackapi和我制作的任何其他常用实用程序函数或常用库放入全局flask上下文的最佳方法是什么,以便可以在任何蓝图中使用它们?
编辑: 这就是我从acuity.handlers导入的方式
import dateutil.parser, datetime, os, json, requests
from jinja2 import Environment, FileSystemLoader
import app.slackapi as slack
from flask import current_app
如果我尝试在app.slackapi中from flask import current_app
不会出错。但是,如果我尝试像这样使用和引用current_app:
import time
from slackclient import SlackClient
from flask import current_app
# instantiate Slack client
slack_client = SlackClient(current_app['SLACK_API_TOKEN'])
出现此错误
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/workers/base.py", line 129, in init_process
self.load_wsgi()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/workers/base.py", line 138, in load_wsgi
self.wsgi = self.app.wsgi()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/app/base.py", line 67, in wsgi
self.callable = self.load()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/app/wsgiapp.py", line 52, in load
return self.load_wsgiapp()
File "/usr/local/lib/python3.5/dist-packages/gunicorn/app/wsgiapp.py", line 41, in load_wsgiapp
return util.import_app(self.app_uri)
File "/usr/local/lib/python3.5/dist-packages/gunicorn/util.py", line 350, in import_app
__import__(module)
File "/opt/slackbot/slackbot/slackbot.py", line 3, in <module>
app = create_app()
File "/opt/slackbot/slackbot/app/__init__.py", line 22, in create_app
from app.acuity import bp as acuity_bp
File "/opt/slackbot/slackbot/app/acuity/__init__.py", line 5, in <module>
from app.acuity import routes
File "/opt/slackbot/slackbot/app/acuity/routes.py", line 4, in <module>
from app.acuity import handlers
File "/opt/slackbot/slackbot/app/acuity/handlers.py", line 3, in <module>
import app.slackapi as slack
File "/opt/slackbot/slackbot/app/slackapi.py", line 10, in <module>
slack_client = SlackClient(current_app['SLACK_API_TOKEN'])
File "/usr/local/lib/python3.5/dist-packages/werkzeug/local.py", line 377, in <lambda>
__getitem__ = lambda x, i: x._get_current_object()[i]
File "/usr/local/lib/python3.5/dist-packages/werkzeug/local.py", line 306, in _get_current_object
return self.__local()
File "/usr/local/lib/python3.5/dist-packages/flask/globals.py", line 51, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
编辑两个:
app/__init__.py
import logging
from logging.handlers import RotatingFileHandler
import os
from flask import Flask, request, current_app
from config import Config
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(config_class)
from app.main import bp as main_bp
app.register_blueprint(main_bp)
from app.acuity import bp as acuity_bp
app.register_blueprint(acuity_bp)
if not app.debug and not app.testing:
if app.config['LOG_TO_STDOUT'] == "True":
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
app.logger.addHandler(stream_handler)
else:
if not os.path.exists(os.path.dirname(__file__) + '/logs'):
os.mkdir(os.path.dirname(__file__) + '/logs')
file_handler = RotatingFileHandler(os.path.dirname(__file__) + '/logs/slackbot.log',
maxBytes=10240, backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Slackbot startup')
return app
app/acuity/__init__.py
from flask import Blueprint
bp = Blueprint('acuity', __name__)
from app.acuity import routes
答案 0 :(得分:0)
这可能不是最优雅的解决方案,但是您可以将这些项放置在 init .py中的create_app(应用程序工厂)函数中。
根据Flask文档,如果您不能执行此操作,则应将代码移至视图函数或CLI命令中。
答案 1 :(得分:0)
为什么不能在create_app()
文件中为应用程序包添加__init__.py
函数,并在此函数中注册蓝图?然后,您可以将current_app
变量导入所需的蓝图中,并根据需要引用current_app
变量。类似于:
__ init __。py :
# .... other package initialization code
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
# initialization of important app components
# database, login_manager, mail, etc....
db.init_app(app)
# register blueprints
from app.acuity.routes import <acuity_blueprint_variable>
from app.main.routes import blueprint
app.register_blueprint(<acuity_blueprint_variable>)
app.register_blueprint(blueprint)
return app
main / routes.py :
# import your flask dependencies then just reference current_app where necessary
from flask import request, redirect, url_for, render_template, current_app, Response
blueprint = flask.Blueprint('main', __name__)
@blueprint.route("/api", methods=["GET"])
def list_routes():
result = []
for rt in current_app.url_map.iter_rules():
result.append({
"methods": list(rt.methods),
"route": str(rt)
})
return flask.jsonify({"routes": result, "total": len(result)})
在上面的示例中,我展示了在current_app
蓝图main
端点内使用list_routes
,该端点仅显示为您的应用程序定义的路由。请注意,在您的create_app
函数中,我正在导入在main.routes
中创建的名为“ blueprint”的蓝图变量,并将此蓝图注册到应用程序,以便可以在此蓝图的路由内引用current_app
变量
希望这很有道理!