Flask和SubdomainDispatcher,应用程序最初是如何运行的?

Flask和SubdomainDispatcher,应用程序最初是如何运行的?,flask,subdomain,Flask,Subdomain,我正在使用Flask构建一个网站,我想使用指定的,但我不知道如何使它工作(它缺少启动服务器的初始运行) 代码如下: 提供的创建应用程序功能: def create_app(database_uri, debug=False): app = Flask(__name__) app.debug = debug # set up your database app.engine = create_engine(database_uri) # add your

我正在使用Flask构建一个网站,我想使用指定的,但我不知道如何使它工作(它缺少启动服务器的初始
运行

代码如下:

提供的创建应用程序功能:

def create_app(database_uri, debug=False):
    app = Flask(__name__)
    app.debug = debug

    # set up your database
    app.engine = create_engine(database_uri)

    # add your modules
    app.register_module(frontend)

    # other setup tasks

    return app
class SubdomainDispatcher(object):

    def __init__(self, domain, create_app):
        self.domain = domain
        self.create_app = create_app
        self.lock = Lock()
        self.instances = {}

    def get_application(self, host):
        host = host.split(':')[0]
        assert host.endswith(self.domain), 'Configuration error'
        subdomain = host[:-len(self.domain)].rstrip('.')
        with self.lock:
            app = self.instances.get(subdomain)
            if app is None:
                app = self.create_app(subdomain)
                self.instances[subdomain] = app
            return app

    def __call__(self, environ, start_response):
        app = self.get_application(environ['HTTP_HOST'])
        return app(environ, start_response)
def make_app(subdomain):
    user = get_user_for_subdomain(subdomain)
    if user is None:
        # if there is no user for that subdomain we still have
        # to return a WSGI application that handles that request.
        # We can then just return the NotFound() exception as
        # application which will render a default 404 page.
        # You might also redirect the user to the main page then
        return NotFound()

    # otherwise create the application for the specific user
    return create_app(user)

application = SubdomainDispatcher('example.com', make_app)
子域调度程序:

def create_app(database_uri, debug=False):
    app = Flask(__name__)
    app.debug = debug

    # set up your database
    app.engine = create_engine(database_uri)

    # add your modules
    app.register_module(frontend)

    # other setup tasks

    return app
class SubdomainDispatcher(object):

    def __init__(self, domain, create_app):
        self.domain = domain
        self.create_app = create_app
        self.lock = Lock()
        self.instances = {}

    def get_application(self, host):
        host = host.split(':')[0]
        assert host.endswith(self.domain), 'Configuration error'
        subdomain = host[:-len(self.domain)].rstrip('.')
        with self.lock:
            app = self.instances.get(subdomain)
            if app is None:
                app = self.create_app(subdomain)
                self.instances[subdomain] = app
            return app

    def __call__(self, environ, start_response):
        app = self.get_application(environ['HTTP_HOST'])
        return app(environ, start_response)
def make_app(subdomain):
    user = get_user_for_subdomain(subdomain)
    if user is None:
        # if there is no user for that subdomain we still have
        # to return a WSGI application that handles that request.
        # We can then just return the NotFound() exception as
        # application which will render a default 404 page.
        # You might also redirect the user to the main page then
        return NotFound()

    # otherwise create the application for the specific user
    return create_app(user)

application = SubdomainDispatcher('example.com', make_app)
主应用程序:

def create_app(database_uri, debug=False):
    app = Flask(__name__)
    app.debug = debug

    # set up your database
    app.engine = create_engine(database_uri)

    # add your modules
    app.register_module(frontend)

    # other setup tasks

    return app
class SubdomainDispatcher(object):

    def __init__(self, domain, create_app):
        self.domain = domain
        self.create_app = create_app
        self.lock = Lock()
        self.instances = {}

    def get_application(self, host):
        host = host.split(':')[0]
        assert host.endswith(self.domain), 'Configuration error'
        subdomain = host[:-len(self.domain)].rstrip('.')
        with self.lock:
            app = self.instances.get(subdomain)
            if app is None:
                app = self.create_app(subdomain)
                self.instances[subdomain] = app
            return app

    def __call__(self, environ, start_response):
        app = self.get_application(environ['HTTP_HOST'])
        return app(environ, start_response)
def make_app(subdomain):
    user = get_user_for_subdomain(subdomain)
    if user is None:
        # if there is no user for that subdomain we still have
        # to return a WSGI application that handles that request.
        # We can then just return the NotFound() exception as
        # application which will render a default 404 page.
        # You might also redirect the user to the main page then
        return NotFound()

    # otherwise create the application for the specific user
    return create_app(user)

application = SubdomainDispatcher('example.com', make_app)
到目前为止,我的代码工作正常,但随后停止。这是正常的,因为不存在以下情况:

if __name__ == "__main__":
    application = create_app(config.DATABASE_URI, debug=True)
    application.run()
使初始服务器运行的代码

我试过这个:

if __name__ == "__main__":
    application = SubdomainDispatcher('example.com', make_app)
    application.run()
但它在以下方面失败了:

AttributeError:“SubdomainDispatcher”对象没有属性“run”


如何使用SubdomainDispatcher运行它?

让我们分析一下您的代码

您创建一个
SubdomainDispatcher
类,该类创建一个
Flask
应用程序
,并基于传入的
主机
返回它

这也是一个
可调用的

问题是
.run
方法是
Flask
对象(应用程序本身)的。 在开发过程中,它仅用于测试应用程序,它适用于单个应用程序

因此,您不能将开发服务器作为一个整体系统来测试它。一次只能测试一个域(应用程序)

if __name__ == "__main__":
    application = SubdomainDispatcher('example.com', make_app)
    app = application.get_application('example.com')
    app.run()
测试服务器不是功能齐全的服务器

更好的解决方案 顺便说一句,我认为如果你解释一下你想要实现什么(而不是你打算如何在烧瓶中实现它:),我们可以找到更好的解决方案。i、 e.使用Flask子域关键字,或使用
@before_request
,根据某些内容本地化应用程序参数。
如果问题只是基于子域加载用户类,则不需要不同的Flask应用程序(特别是因为您使用的是相同的代码库),但在请求之前只需要一个
@处理程序。

要将
SubdomainDispatcher
与Flask本地开发服务器一起使用,我将大部分代码从
flask.flask.run
复制到一个单独的函数中,并连接到
SubdomainDispatcher
中间件中。通过werkzeug.serving.run_simple完成重物搬运

def rundevserver(host=None, port=None, domain='', debug=True, **options):
    from werkzeug.serving import run_simple

    if host is None:
        host = '127.0.0.1'
    if port is None:
        port = 5000
    options.setdefault('use_reloader', debug)
    options.setdefault('use_debugger', debug)

    app = SubdomainDispatcher(create_app, domain, debug=debug)

    run_simple(host, port, app, **options)

有关更多详细信息,请参阅我的博文:

这是一个输入错误,如果我调用
application.run()
,我会出现错误“AttributeError:“SubdomainDispatcher”对象没有属性“run”。更确切地说,我的Flask应用程序会在数据库中为每个子域(表用户)加载一个条目。我从请求前的
@开始,但我认为这不是独立于应用程序的,以后可能会导致问题。使用此dispatcher,我确信每个子域都有且只有一个用户实例,这是正确的。顺便问一下,您知道在
make_app
函数中是否有可能重定向用户?在
@请求之前
您认为错误:)。您可以控制用户加载,并在每个请求之前加载它,以便确保加载的类的正确性。在您的方法中,您试图在没有技术原因的情况下保持应用程序的两个实例处于活动状态,这只会增加调试的复杂性。对于重定向,不需要。在创建
应用程序
以提供内容之前,您尝试登录用户。在您的方法中,您需要创建另一个
应用程序
(ugh)以仅重定向。在请求前使用
@before\u request
您可以运行
请求
代理和所有flask套件,这样您就可以
以常规方式重定向用户。:)