すべてのルートに追加するプレフィックスがあります。現在、すべての定義でルートに定数を追加しています。これを自動的に行う方法はありますか?
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"
答えは、このアプリケーションの提供方法によって異なります。
このアプリケーションをWSGIコンテナ(mod_wsgi、uwsgi、gunicornなど)内で実行すると仮定します。実際にmount、その接頭辞その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/"
APPLICATION_ROOT
設定値を設定すると、Flaskのセッション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 __== '__main__':
app.run('localhost', 5000)
一方、WSGIコンテナのルートでFlaskアプリケーションを実行し、リクエストをプロキシする場合(たとえば、FastCGIを実行する場合、またはnginxがproxy_pass
-である場合)スタンドアロンuwsgi
/gevent
サーバーへのサブエンドポイントのリクエストを行うと、次のいずれかを実行できます。
DispatcherMiddleware
from werkzeug
を使用(またはPrefixMiddleware
from su27's answer )使用しているスタンドアロンWSGIサーバーにアプリケーションをサブマウントします。 (使用するコードについては、上記のアプリを適切にサブマウントする例を参照してください)。ルートを青写真に入れることができます。
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')
APPLICATION_ROOT
はこの目的ではないことに注意してください。
必要なことは、ミドルウェアを作成して次の変更を加えることだけです。
PATH_INFO
を変更して、接頭辞付きURLを処理します。SCRIPT_NAME
を変更して、接頭辞付きURLを生成します。このような:
class PrefixMiddleware(object):
def __init__(self, app, prefix=''):
self.app = app
self.prefix = prefix
def __call__(self, environ, start_response):
if environ['PATH_INFO'].startswith(self.prefix):
environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):]
environ['SCRIPT_NAME'] = self.prefix
return self.app(environ, start_response)
else:
start_response('404', [('Content-Type', 'text/plain')])
return ["This url does not belong to the app.".encode()]
次のように、ミドルウェアでアプリをラップします。
from flask import Flask, url_for
app = Flask(__name__)
app.debug = True
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/foo')
@app.route('/bar')
def bar():
return "The URL for this page is {}".format(url_for('bar'))
if __== '__main__':
app.run('0.0.0.0', 9010)
http://localhost:9010/foo/bar
にアクセスして、
正しい結果が得られます:The URL for this page is /foo/bar
必要に応じて、Cookieドメインを設定することを忘れないでください。
このソリューションは Larivact's Gist で与えられます。 APPLICATION_ROOT
はこの仕事用ではありませんが、そうです。本当に紛らわしいです。
これは、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ルート関数requires a route
が最初の位置引数であるという事実に依存しています。
次のように使用できます。
app = Flask(__name__)
app.route = prefix_route(app.route, '/your_prefix')
NB:接頭辞に変数を使用して(たとえば、/<prefix>
に設定する)、@app.route(...)
で修飾する関数でこの接頭辞を処理することはできません。その場合、装飾された関数でprefix
パラメーターを宣言する必要があります。さらに、送信されたプレフィックスをいくつかのルールに対してチェックし、チェックが失敗した場合に404を返すこともできます。 404カスタム再実装を回避するには、from werkzeug.exceptions import NotFound
を確認し、チェックが失敗した場合はraise NotFound()
を使用してください。
したがって、これに対する有効な答えは次のとおりであると考えています。プレフィックスは、開発が完了したときに使用する実際のサーバーアプリケーションで構成する必要があります。 Apache、nginxなど.
ただし、デバッグ時にFlaskアプリを実行中に開発中にこれを機能させたい場合は、 this 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 __== '__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/
別の完全に異なる方法は、uwsgi
にmountpointsを使用することです。
ドキュメントから 同じプロセスで複数のアプリをホストする ( permalink )。
uwsgi.ini
に追加します
[uwsgi]
mount = /foo=main.py
manage-script-name = true
# also stuff which is not relevant for this, but included for completeness sake:
module = main
callable = app
socket = /tmp/uwsgi.sock
ファイルmain.py
を呼び出さない場合は、mount
とmodule
の両方を変更する必要があります
main.py
は次のようになります。
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/bar')
def bar():
return "The URL for this page is {}".format(url_for('bar'))
# end def
そして、nginx config(完全性のために):
server {
listen 80;
server_name example.com
location /foo {
include uwsgi_params;
uwsgi_pass unix:///temp/uwsgi.sock;
}
}
example.com/foo/bar
を呼び出すと、フラスコのurl_for('bar')
が自動的に適応するため、/foo/bar
が表示されます。そうすれば、プレフィックスの問題なくリンクが機能します。
私は「context-root」と呼ばれる同様のものが必要でした。 WSGIScriptAliasを使用して/etc/httpd/conf.d/の下のconfファイルで実行しました。
<VirtualHost *:80>
WSGIScriptAlias /myapp /home/<myid>/myapp/wsgi.py
<Directory /home/<myid>/myapp>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
そのため、次のようにアプリにアクセスできます。 http:// localhost:5000/myapp
ガイドを参照してください- http://modwsgi.readthedocs.io/en/develop/user-guides/quick-configuration-guide.html
app
全体にプレフィックスを追加する場合は、常に以下を使用することを好みます。
app = Flask(__name__, root_path='/operators')
クリーンでクリアな。
flaskとPHPアプリがnginxとPHP5.6を共存させる私のソリューション
ルートにFlaskを、サブディレクトリにPHPを保持
Sudo vi /etc/php/5.6/fpm/php.ini 1行追加cgi.fix_pathinfo = 0
Sudo vi /etc/php/5.6/fpm/pool.d/www.conf listen = /run/php/php5.6-fpm.sock
uWSGI
Sudo vi/etc/nginx/sites-available/default PHPのネストされた場所を使用し、FLASKをルートに残します
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.php index.nginx-debian.html;
server_name _;
# Serve a static file (ex. favico) outside static dir.
location = /favico.ico {
root /var/www/html/favico.ico;
}
# Proxying connections to application servers
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
}
location /pcdp {
location ~* \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
location /phpmyadmin {
location ~* \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php7.0-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# # With php7.0-fpm:
# fastcgi_pass unix:/run/php/php7.0-fpm.sock;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
場所の一致を理解する必要があります(なし):修飾子が存在しない場合、場所はプレフィックスの一致として解釈されます。これは、指定された場所がリクエストURIの先頭と照合され、一致を判断することを意味します。 =:等号が使用されている場合、要求URIが指定された場所と完全に一致する場合、このブロックは一致と見なされます。 〜:チルダ修飾子が存在する場合、この場所は大文字と小文字を区別する正規表現の一致として解釈されます。 〜*:チルダとアスタリスクの修飾子が使用される場合、ロケーションブロックは大文字と小文字を区別しない正規表現の一致として解釈されます。 ^〜:カラットとチルダ修飾子が存在し、このブロックが最適な非正規表現一致として選択されている場合、正規表現一致は行われません。
Nginxの「場所」の説明から、順序は重要です。
特定の要求に一致する場所を見つけるために、nginxは最初にプレフィックス文字列(プレフィックスの場所)を使用して定義された場所を確認します。その中で、最も長いプレフィックスを持つ場所が選択され、記憶されます。次に、構成ファイルでの出現順に正規表現がチェックされます。正規表現の検索は最初の一致で終了し、対応する構成が使用されます。正規表現と一致するものが見つからない場合は、以前に記憶されたプレフィックスロケーションの設定が使用されます。
その意味は:
最初の=。 (「最長一致プレフィックス」一致)暗黙のプレフィックス。 (「最長一致プレフィックス」一致)次に正規表現。 (最初の一致)
from flask import Flask
app = Flask(__name__)
app.register_blueprint(bp, url_prefix='/abc/123')
if __== "__main__":
app.run(debug='True', port=4444)
bp = Blueprint('burritos', __name__,
template_folder='templates')
@bp.route('/')
def test():
return "success"