【问题标题】:Flask - Can't override default subdomain for blueprints needing a different subdomainFlask - 无法覆盖需要不同子域的蓝图的默认子域
【发布时间】:2020-05-29 22:09:20
【问题描述】:

我有一个 Flask 项目/应用程序,并希望主要从 app.example.com 提供服务。我在这个应用程序中也有一个蓝图,只能从api.example.com 提供。

现在,如果我将 app 设置为默认子域,我将无法在其他应该从不同子域(例如 api)提供的蓝图中覆盖此默认值。事实上,任何使用不同子域创建的蓝图都会出现 404。

换句话说,下面的代码不起作用(api.example.com/test2 将 404):

# -*- coding: utf-8 -*-

from flask import Flask, Blueprint

app = Flask(__name__)
app.config['SERVER_NAME'] = 'example.com'
app.url_map.default_subdomain = 'app' # set default subdomain, intending to override it below for `api.*`

appbp = Blueprint('app', 'app')
apibp = Blueprint('api', 'api') 


@appbp.route('/test1')
def app_hello():
    # this works (app.example.com/test1)
    return 'appbp.app_hello'


@apibp.route('/test2')
def api_hello():
    # this will 404 (api.example.com/test2)
    return 'apibp.api_hello'


app.register_blueprint(appbp) # this works, serves from `app.example.com`
app.register_blueprint(apibp, subdomain='api') # doesn't work, `api.example.com/test2` will 404, so will `app.example.com/test2` (tried just in case it was using the default subdomain instead)

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8888, debug=True)

但是,如果我不设置默认子域,而是在我每次注册蓝图时设置一个子域,它对appapi 都有效:

# -*- coding: utf-8 -*-

from flask import Flask, Blueprint

app = Flask(__name__)
app.config['SERVER_NAME'] = 'example.com'
# app.url_map.default_subdomain = 'app' # now try without a default

appbp = Blueprint('app', 'app') 
apibp = Blueprint('api', 'api')


@appbp.route('/test1')
def app_hello():
    # this works (app.example.com/test1)
    return 'appbp.app_hello'


@apibp.route('/test2')
def api_hello():
    # this works (api.example.com/test2)
    return 'apibp.api_hello'


app.register_blueprint(appbp, subdomain='app') # works, explicitly set subdomain on each blueprint
app.register_blueprint(apibp, subdomain='api') # works, explicitly set subdomain on each blueprint

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8888, debug=True)

在这两个示例中,蓝图似乎都注册到了正确的子域:

 <Rule 'app|/test1' (OPTIONS, GET, HEAD) -> app.app_hello>
 <Rule 'api|/test2' (OPTIONS, GET, HEAD) -> api.api_hello>

但是,很明显,设置 app.url_map.default_subdomain 打算稍后覆盖它和手动显式设置子域之间是有区别的。

知道这里发生了什么吗?

奖励积分:以下哪一种是设置子域的首选方式?我已经看到它是双向的。

app.register_blueprint(apibp, subdomain='api')

对比

apibp = Blueprint('api', 'api', subdomain='api')
app.register_blueprint(apibp)

【问题讨论】:

    标签: python flask subdomain blueprint


    【解决方案1】:

    缺少的是subdomain_matching option for Flask()

    subdomain_matching – 匹配路由时考虑相对于SERVER_NAME 的子域。默认为 False。

    由于app是一个相对名称,您需要将其设置为True

    app = Flask(__name__, subdomain_matching=True)
    

    这过去是隐式完成的,但从 Flask 1.0 开始,它是一个显式开关。之所以进行更改,是因为不同的人对设置 SERVER_NAME 的含义有不同的期望,请参阅 Flask issue #998

    至于您在哪里设置subdomain 选项,这是您的选择。如果您在不同的上下文中重用蓝图,那么在app.register_blueprint() 调用中设置子域选项更有意义,而在Blueprint() 实例调用中设置它可能会使其在创建该蓝图对象时更具自我记录性更接近您的路线,因此希望让处理该代码的人更清楚地知道他们只影响特定的子域。

    【讨论】:

      猜你喜欢
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-12
      • 2020-08-23
      • 1970-01-01
      • 2016-09-14
      • 2014-09-16
      相关资源
      最近更新 更多