모든 경로에 추가하려는 접두사가 있습니다. 지금은 모든 정의에서 상수를 경로에 추가합니다. 이 작업을 자동으로 수행하는 방법이 있습니까?
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 컨테이너 내부에 하위 마운트 됨
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/"
APPLICATION_ROOT
구성 값을 설정하면 Flask의 세션 쿠키를 해당 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)
앱에 대한 요청 프록시
반면에, WSGI 컨테이너의 루트에서 Flask 애플리케이션을 실행하고 이에 대한 요청을 프록시하는 경우 (예 : FastCGI를 사용하는 경우 또는 nginx가 proxy_pass
하위 엔드 포인트에 대한 요청을 -ing하는 경우) 독립 실행 형 uwsgi
/ gevent
서버에 다음 중 하나를 수행 할 수 있습니다.
답변
경로를 청사진에 넣을 수 있습니다.
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"
그런 다음 접두사를 사용하여 애플리케이션에 Blueprint를 등록합니다.
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 __name__ == '__main__':
app.run('0.0.0.0', 9010)
방문 http://localhost:9010/foo/bar
,
올바른 결과를 얻을 수 있습니다. The URL for this page is /foo/bar
필요한 경우 쿠키 도메인을 설정하는 것을 잊지 마십시오.
이 솔루션은 Larivact의 요점에 의해 제공됩니다 . 는 APPLICATION_ROOT
그것을 할 수처럼 보이지만,이 작업이 아니다. 정말 혼란 스럽습니다.
답변
이것은 Flask / werkzeug 답변보다 파이썬 답변에 가깝습니다. 그러나 그것은 간단하고 작동합니다.
저처럼 애플리케이션 설정 ( .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
틀림없이, 이것은 다소 hackish하고 플라스크 경로 기능이 있다는 사실에 의존 필요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 앱을 실행하는 동안 개발 중에이 작업을 수행하려면 이 요점을 살펴보십시오 .
플라스크가 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)
독립 플라스크 응용 프로그램으로 위의 코드를 실행할 때 지금, 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
.
동일한 프로세스에서 여러 앱 호스팅에 대한 문서 ( 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 구성 (완전성을 위해 다시) :
server {
listen 80;
server_name example.com
location /foo {
include uwsgi_params;
uwsgi_pass unix:///temp/uwsgi.sock;
}
}
이제 호출 은 자동으로 조정되므로 flask의 반환 된대로 example.com/foo/bar
표시 됩니다. 그러면 링크가 접두사 문제없이 작동합니다./foo/bar
url_for('bar')
답변
from flask import Flask
app = Flask(__name__)
app.register_blueprint(bp, url_prefix='/abc/123')
if __name__ == "__main__":
app.run(debug='True', port=4444)
bp = Blueprint('burritos', __name__,
template_folder='templates')
@bp.route('/')
def test():
return "success"