Добавление префикса ко всем маршрутам колбы
У меня есть префикс, что я хочу добавить к каждому маршруту. Прямо сейчас я добавляю константу в маршрут при каждом определении. Есть ли способ сделать это автоматически?
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"
8 ответов:
ответ зависит от того, как вы служите это приложение.
подсоединен внутри другого контейнера WSGI
предполагая, что вы собираетесь запустить это приложение внутри контейнера WSGI (mod_wsgi, uwsgi, gunicorn и т. д.); Вам нужно на самом деле mount, с этим префиксом приложение как часть этого контейнера WSGI (все, что говорит WSGI будет делать) и установить ваш
APPLICATION_ROOTзначение config в префикс: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значение конфигурации просто ограничивает cookie сеанса Flask этим префиксом URL. Все остальное будет автоматически обрабатываться для вас с помощью Flask и Werkzeug отличные возможности обработки WSGI.пример правильного подсоединения вашего приложения
если вы не уверены, что означает первый абзац, взгляните на этот пример приложения с колбой, установленной внутри это:
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'D, или если nginx
proxy_pass-ing запросы на суб-конечную точку для вашего автономногоuwsgi/geventсервер, то вы можете либо:
- используйте чертеж, как указывает Мигель в его ответ.
- или использовать
DispatcherMiddlewareСwerkzeug(илиPrefixMiddlewareС су27 это) в суб-Маунт-приложения в изолированной тут 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 __name__ == '__main__': app.run('0.0.0.0', 9010)посетить
http://localhost:9010/foo/bar,вы получите правильный результат:
The URL for this page is /foo/barи не забудьте установить домен cookie, если вам нужно.
это решение дано Larivact это. Элемент
APPLICATION_ROOTне для этой работы, хотя она выглядит как. Это действительно сбивает с толку.
это скорее ответ python, чем ответ Flask/werkzeug; но это просто и работает.
если, как и я, вы хотите, чтобы ваши настройки приложения (загружается из
.inifile) чтобы также содержать префикс вашего приложения 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 и зависит от того, что функция маршрута колбы требует 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 в debug, взгляните на в этом суть.
колбы
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/
Мне нужен был подобный так называемый"контекст-корень". Я сделал это в файле conf под /etc/httpd/conf.d / с помощью WSGIScriptAlias:
приложение.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
другой совершенно другой способ - с mountpoints на
uwsgi.из документа о размещение нескольких приложений в одном процессе (ссылка).
в своем
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; } }называют
example.com/foo/barпоявится/foo/barкак возвращено колбыurl_for('bar'), так как он автоматически адаптируется. Таким образом ваши ссылки будут работать без проблем префикс.
Я всегда предпочитаю использовать следующее, Когда речь идет о добавлении префикса на всю
app:app = Flask(__name__, root_path='/operators')чистый и ясный.
Comments