125

すべてのルートに追加したいプレフィックスがあります。現在、すべての定義でルートに定数を追加しています。これを自動的に行う方法はありますか?

PREFIX = "/abc/123"

@app.route(PREFIX + "/")
def index_page():
  return "This is a website about burritos"

@app.route(PREFIX + "/about")
def about_page():
  return "This is a website about burritos"
4

13 に答える 13

122

ルートをブループリントに入れることができます:

bp = Blueprint('burritos', __name__,
                        template_folder='templates')

@bp.route("/")
def index_page():
  return "This is a website about burritos"

@bp.route("/about")
def about_page():
  return "This is a website about burritos"

次に、プレフィックスを使用してブループリントをアプリケーションに登録します。

app = Flask(__name__)
app.register_blueprint(bp, url_prefix='/abc/123')
于 2013-09-23T21:24:12.867 に答える
88

答えは、このアプリケーションをどのように提供しているかによって異なります。

別の WSGI コンテナの内部にサブマウント

このアプリケーションを WSGI コンテナ (mod_wsgi、uwsgi、gunicorn など) 内で実行すると仮定します。実際に、そのプレフィックスでアプリケーションをその WSGI コンテナーのサブパーツとしてマウントし(WSGI を話すものなら何でも)、構成APPLICATION_ROOT値をプレフィックスに設定する必要があります。

app.config["APPLICATION_ROOT"] = "/abc/123"

@app.route("/")
def index():
    return "The URL for this page is {}".format(url_for("index"))

# Will return "The URL for this page is /abc/123/"

config 値を設定すると、 APPLICATION_ROOTFlask のセッション Cookie がその URL プレフィックスに制限されます。他のすべては、Flask と Werkzeug の優れた WSGI 処理機能によって自動的に処理されます。

アプリを適切にサブマウントする例

最初の段落の意味がわからない場合は、内部に Flask がマウントされたこのサンプル アプリケーションを見てください。

from flask import Flask, url_for
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware

app = Flask(__name__)
app.config['APPLICATION_ROOT'] = '/abc/123'

@app.route('/')
def index():
    return 'The URL for this page is {}'.format(url_for('index'))

def simple(env, resp):
    resp(b'200 OK', [(b'Content-Type', b'text/plain')])
    return [b'Hello WSGI World']

app.wsgi_app = DispatcherMiddleware(simple, {'/abc/123': app.wsgi_app})

if __name__ == '__main__':
    app.run('localhost', 5000)

アプリへのリクエストのプロキシ

一方、Flask アプリケーションを WSGI コンテナのルートで実行し、それにリクエストをプロキシする場合 (たとえば、FastCGI を実行している場合、または nginx がproxy_passサブエンドポイントのリクエストを送信している場合)スタンドアロンuwsgi/geventサーバーに接続すると、次のいずれかを実行できます。

  • Miguelが回答で指摘しているように、Blueprint を使用します。
  • またはDispatcherMiddlewarefrom werkzeug(またはPrefixMiddlewarefrom su27's answer ) を使用して、使用しているスタンドアロン WSGI サーバーにアプリケーションをサブマウントします。(使用するコードについては、上記のアプリを適切にサブマウントする例を参照してください)。
于 2013-09-23T19:57:47.667 に答える
13

これは、Flask/werkzeug の回答よりも Python の回答に近いものです。しかし、それはシンプルで機能します。

私のように、アプリケーション設定 (.iniファイルからロード) に Flask アプリケーションのプレフィックスも含めたい場合 (したがって、デプロイ中に値を設定するのではなく、実行時に値を設定する必要がある場合)、次のオプションを選択できます。

def prefix_route(route_function, prefix='', mask='{0}{1}'):
  '''
    Defines a new route function with a prefix.
    The mask argument is a `format string` formatted with, in that order:
      prefix, route
  '''
  def newroute(route, *args, **kwargs):
    '''New function to prefix the route'''
    return route_function(mask.format(prefix, route), *args, **kwargs)
  return newroute

おそらく、これはいくぶんハックであり、Flask ルート関数が最初の位置引数として a を必要とするという事実に依存しています。route

次のように使用できます。

app = Flask(__name__)
app.route = prefix_route(app.route, '/your_prefix')

注意: プレフィックスで変数を使用できること (たとえば、 に設定することによって/<prefix>)が可能であることは何の価値もありません@app.route(...)。そうする場合、明らかにprefix、装飾された関数でパラメーターを宣言する必要があります。さらに、送信されたプレフィックスをいくつかのルールに照らしてチェックし、チェックが失敗した場合は 404 を返したい場合があります。404 カスタムの再実装を回避するために、チェックが失敗した場合はfrom werkzeug.exceptions import NotFound次のようにしてください。raise NotFound()

于 2016-06-17T09:51:26.827 に答える
5

したがって、これに対する有効な答えは次のとおりだと思います。プレフィックスは、開発が完了したときに使用する実際のサーバー アプリケーションで構成する必要があります。アパッチ、nginx など

ただし、デバッグで Flask アプリを実行している開発中にこれを機能させたい場合は、この gistをご覧ください。

フラスコDispatcherMiddlewareが助けに来ました!

後世のためにここにコードをコピーします。

"Serve a Flask app on a sub-url during localhost development."

from flask import Flask


APPLICATION_ROOT = '/spam'


app = Flask(__name__)
app.config.from_object(__name__)  # I think this adds APPLICATION_ROOT
                                  # to the config - I'm not exactly sure how!
# alternatively:
# app.config['APPLICATION_ROOT'] = APPLICATION_ROOT


@app.route('/')
def index():
    return 'Hello, world!'


if __name__ == '__main__':
    # Relevant documents:
    # http://werkzeug.pocoo.org/docs/middlewares/
    # http://flask.pocoo.org/docs/patterns/appdispatch/
    from werkzeug.serving import run_simple
    from werkzeug.wsgi import DispatcherMiddleware
    app.config['DEBUG'] = True
    # Load a dummy app at the root URL to give 404 errors.
    # Serve app at APPLICATION_ROOT for localhost development.
    application = DispatcherMiddleware(Flask('dummy_app'), {
        app.config['APPLICATION_ROOT']: app,
    })
    run_simple('localhost', 5000, application, use_reloader=True)

上記のコードをスタンドアロンの Flask アプリとして実行すると、http://localhost:5000/spam/が表示されますHello, world!

別の回答へのコメントで、次のようなことをしたいと述べました。

from flask import Flask, Blueprint

# Let's pretend module_blueprint defines a route, '/record/<id>/'
from some_submodule.flask import module_blueprint

app = Flask(__name__)
app.config['APPLICATION_ROOT'] = '/api'
app.register_blueprint(module_blueprint, url_prefix='/some_submodule')
app.run()

# I now would like to be able to get to my route via this url:
# http://host:8080/api/some_submodule/record/1/

私の不自然な例に適用DispatcherMiddlewareする:

from flask import Flask, Blueprint
from flask.serving import run_simple
from flask.wsgi import DispatcherMiddleware

# Let's pretend module_blueprint defines a route, '/record/<id>/'
from some_submodule.flask import module_blueprint

app = Flask(__name__)
app.config['APPLICATION_ROOT'] = '/api'
app.register_blueprint(module_blueprint, url_prefix='/some_submodule')
application = DispatcherMiddleware(Flask('dummy_app'), {
    app.config['APPLICATION_ROOT']: app
})
run_simple('localhost', 5000, application, use_reloader=True)

# Now, this url works!
# http://host:8080/api/some_submodule/record/1/
于 2016-05-18T19:52:07.923 に答える
0

su27さんの答えは正しいと思います。そして、私はgeventを使用しています。ここに私のコードがあり、正常に動作します:

from gevent import pywsgi

# your flask code ...
# app = Flask(__name__)

if __name__ == "__main__":
    class MyHandler(pywsgi.WSGIHandler):
        def get_environ(self):
            prefix = "/your_prefix"
            env = super().get_environ()
            if env['PATH_INFO'].startswith(prefix):
                env['PATH_INFO'] = env['PATH_INFO'][len(prefix):]
                env['SCRIPT_NAME'] = prefix
            return env
    
    server = pywsgi.WSGIServer(('', 8080), app, handler_class=MyHandler)
    server.serve_forever()
于 2021-04-07T08:38:12.773 に答える