简体   繁体   English

Flask 蓝图架构问题

[英]Flask blueprint architecture issues

I'm new with using flask so I'm doing a lot of research to find out what the best way to structure my application.我是使用烧瓶的新手,所以我做了很多研究,以找出构建我的应用程序的最佳方式。 I've been following app factories and using blueprints, but I'm having trouble figuring out how to use application wide libraries and keep the app context.我一直在关注应用程序工厂并使用蓝图,但我无法弄清楚如何使用应用程序范围的库并保持应用程序上下文。 For example here is my app structure:例如,这是我的应用程序结构:

├── 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 and Acuity are blueprints. Main 和 Acuity 是蓝图。 Main doesn't do anything and the only endpoints are in acuity. Main 不做任何事情,唯一的端点是敏锐度。 In acuity.handlers I'm importing in app.slackapi but can't use current_app no matter how I slice it.在 acuity.handlers 中,我在 app.slackapi 中导入,但无论我如何切片都无法使用 current_app。 I need to use the app context in order to access the logging and config vars.我需要使用应用程序上下文才能访问日志记录和配置变量。

What's the best way to put the slackapi and any other common utility functions or common libraries I make into the global flask context so that I can use them inside of any of the blueprints?将 slackapi 和我制作的任何其他常用实用程序函数或常用库放入全局烧瓶上下文中以便我可以在任何蓝图中使用它们的最佳方法是什么?

EDIT: This is how I'm importing from acuity.handlers编辑:这就是我从 acuity.handlers 导入的方式

import dateutil.parser, datetime, os, json, requests
from jinja2 import Environment, FileSystemLoader
import app.slackapi as slack
from flask import current_app

If I try to from flask import current_app in app.slackapi it doesn't error.如果我尝试from flask import current_app in app.slackapi 它不会出错。 But if I try to use and reference current_app like this:但是,如果我尝试像这样使用和引用 current_app:

import time
from slackclient import SlackClient
from flask import current_app

# instantiate Slack client
slack_client = SlackClient(current_app['SLACK_API_TOKEN'])

This error arises出现这个错误

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.

EDIT TWO: app/__init__.py编辑二: 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

Why can't you add a create_app() function within your __init__.py file for your app package and register your blueprints within this function?为什么不能在应用程序包的__init__.py文件中添加create_app()函数并在该函数中注册蓝图? Then you can just import the current_app variable in your desired blueprint and reference the current_app variable as necessary.然后,您可以在所需的蓝图中导入current_app变量,并根据需要引用current_app变量。 Something along the lines of:类似的东西:

__init__.py : __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 :主要/路线.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)})

In the example above, I showed using current_app within the main blueprint list_routes endpoint which simply shows the routes defined for your application.在上面的示例中,我展示了在main蓝图list_routes端点中使用current_app ,该端点仅显示为您的应用程序定义的路由。 Note within your create_app function I am importing the blueprint variable I created within main.routes called 'blueprint' and registering this blueprint to the app so references to current_app variable can be made inside this blueprint's routes.请注意,在您的create_app函数中,我正在导入我在main.routes创建的名为“blueprint”的蓝图变量,并将此蓝图注册到应用程序,以便可以在此蓝图的路由中引用current_app变量。

Hopefully that makes sense!希望这是有道理的!

It may not be the most elegant solution, but you can place the items inside of your create_app (app factory) function in init .py.它可能不是最优雅的解决方案,但您可以将项目放在init .py 中的 create_app(应用程序工厂)函数中。

If you can't do that, as per the Flask docs - you should move the code into a view function or CLI command.如果您不能这样做,根据 Flask 文档 - 您应该将代码移动到视图函数或 CLI 命令中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM