Как я могу загрузить проект Flask в субдомен на моем сервере? [Дубликат]

Это то, что я использую:

# Generate a [0-9a-zA-Z] string
ALPHABET = map(str,range(0, 10)) + map(chr, range(97, 123) + range(65, 91))

def encode_id(id_number, alphabet=ALPHABET):
    """Convert an integer to a string."""
    if id_number == 0:
        return alphabet[0]

    alphabet_len = len(alphabet) # Cache

    result = ''
    while id_number > 0:
        id_number, mod = divmod(id_number, alphabet_len)
        result = alphabet[mod] + result

    return result

def decode_id(id_string, alphabet=ALPHABET):
    """Convert a string to an integer."""
    alphabet_len = len(alphabet) # Cache
    return sum([alphabet.index(char) * pow(alphabet_len, power) for power, char in enumerate(reversed(id_string))])

Это очень быстро и может принимать длинные целые числа.

66
задан davidism 4 June 2016 в 01:21
поделиться

8 ответов

Ответ зависит от того, как вы обслуживаете это приложение.

Подмонтировано внутри другого контейнера 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 просто ограничивает файл cookie сеанса флешки этим префиксом URL.

Пример правильной установки вашего приложения

Если вы не знаете, что означает первый абзац, это означает, что все остальные будут автоматически обработаны для вас превосходными возможностями WSGI для Flask и Werkzeug. , посмотрите на это примерное приложение с 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 и запросы проксирования к нему (например, если это FastCGI'd, или если nginx является proxy_pass -потребителями запросов для вспомогательной точки к вашему автономному uwsgi / gevent, вы можете либо:

  • Использовать план, так как Мигель указывает в свой ответ .
  • или используйте DispatcherMiddleware из werkzeug (или PrefixMiddleware из ответа su27 ), чтобы подключить ваше приложение на автономном сервере WSGI, который вы используете. (См. Пример правильной подстройки вашего приложения выше для используемого кода.)
55
ответ дан Community 17 August 2018 в 20:32
поделиться
  • 1
    Этот не работает по состоянию на сегодняшний день (13 мая 2014 года) в версии разработки колбы и 10.0+. (Ваша индексная страница дает URL для этой страницы: / ). Я не уверен, что это было непреднамеренное поведение (оно не похоже на то, что оно было, поскольку оно все еще находится в тестах на фляж) – jknupp 13 May 2014 в 20:47
  • 2
    – Sean Vieira 13 May 2014 в 21:15
  • 3
  • 4
    @jknupp - вот в чем проблема - вам нужно будет на самом деле смонтировать приложение как часть более крупного приложения (все, что говорит WSGI). Я взвесил пример gist и обновил свой ответ, чтобы уточнить, что я предполагаю, что среда WSGI не смонтирована, а не автономная среда WSGI за прокси-сервером, которая только переадресовывает sub -path. – Sean Vieira 16 May 2014 в 06:04
  • 5
    Это работает, используя подход DispatcherMiddleware, когда запускается колба сама по себе. Не может показаться, что это работает, когда бежит за Гуникорн. – Justin 23 September 2015 в 19:32
  • 6
    – Sean Vieira 23 September 2015 в 20:54
  • 7
    @ Если вам не нужно переопределять любую из этих вещей, вам нужно указать Gunicorn на экземпляр DispatcherMiddleware. – davidism 23 September 2015 в 22:50
  • 8
    да, это, кажется, абсолютно не влияет. – Jacob 15 April 2016 в 14:44

Это скорее ответ на python, чем ответ 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

Возможно, это несколько хакерское и полагается на то, что функция маршрута колбы требует 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(), если проверка завершилась неудачно.

6
ответ дан 7heo.tk 17 August 2018 в 20:32
поделиться
  • 1
    @AlexCory Не удается определить, какие "больные" ты имеешь в виду. Я думаю, что оба применяются. – PascalVKooten 6 July 2017 в 16:57

Мне нужен был подобный так называемый «контекст-корень». Я сделал это в файле conf под /etc/httpd/conf.d/, используя WSGIScriptAlias:

myapp.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

1
ответ дан dganesh2002 17 August 2018 в 20:32
поделиться

Другим совершенно другим способом является точка монтирования в uwsgi.

Из документа doc about Хостинг нескольких приложений в одном и том же процессе ( 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;
  }
}

Теперь вызов example.com/foo/bar отобразит /foo/bar, как возвращено флягой url_for('bar'), так как оно автоматически адаптируется. Таким образом, ваши ссылки будут работать без проблем с префиксами.

1
ответ дан luckydonald 17 August 2018 в 20:32
поделиться

Вы можете поместить свои маршруты в план:

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')
63
ответ дан Miguel 17 August 2018 в 20:32
поделиться
  • 1
    Привет Мигель; знаете ли вы разницу между регистрацией url_prefix для чертежа, как вы это делали ниже, с app.register_blueprint и между его регистрацией, когда вы создаете объект Blueprint выше, передавая url_prefix='/abc/123? Спасибо! – aralar 26 December 2014 в 22:22
  • 2
    Разница заключается в том, что наличие префикса URL-адреса в вызове register_blueprint дает приложению свободу для «монтирования». план где угодно, или даже монтировать один и тот же план несколько раз на разных URL-адресах. Если вы поместите префикс в сам план, вы упростите его для приложения, но у вас будет меньше гибкости. – Miguel 27 December 2014 в 02:30
  • 3
    Спасибо!! Это очень полезно. Меня смутило явное избыточность, но я вижу компромисс между двумя вариантами. – aralar 27 December 2014 в 02:33
  • 4
    И на самом деле, я никогда не пробовал этого, но вполне вероятно, что вы можете комбинировать префиксы URL как в плане, так и в приложении, с префиксом кулака приложения, за которым следует префикс проекта. – Miguel 27 December 2014 в 02:59
  • 5
    Обратите внимание, что необходимо зарегистрировать проект после функций blueprint.route. – Quint 26 March 2017 в 17:20

Итак, я считаю, что правильный ответ на этот вопрос: префикс должен быть настроен в фактическом серверном приложении, которое вы используете, когда разработка завершена. Apache, 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/
3
ответ дан Monkpit 17 August 2018 в 20:32
поделиться
  • 1
    «Итак, я считаю, что правильный ответ на этот вопрос: префикс должен быть настроен в фактическом серверном приложении, которое вы используете, когда разработка завершена. Apache, nginx и т. Д. & Quot; Проблема заключается в перенаправлении; если у вас есть префикс и он не настроен в Flask, тогда, когда он перенаправляется вместо перехода на / yourprefix / path / to / url, он просто переходит в / path / to / url. Есть ли способ настроить в nginx или Apache префикс? – Jordan Reiter 1 September 2016 в 23:00
  • 2
    То, как я, вероятно, сделаю это, - это просто использовать инструмент управления конфигурацией, такой как марионетка или шеф-повар, и установить префикс там, а затем заставить инструмент распространять это изменение в файлы конфигурации, куда ему нужно идти. Я не собираюсь даже притворяться, что я знаю, о чем говорю, для apache или nginx. Поскольку этот вопрос / ответ был специфичен для python, я бы рекомендовал вам опубликовать ваш сценарий как отдельный вопрос. Если вы сделаете это, не стесняйтесь ссылаться на вопрос здесь! – Monkpit 2 September 2016 в 16:01

Вы должны заметить, что APPLICATION_ROOT для этой цели НЕ.

Все, что вам нужно сделать, это написать промежуточное программное обеспечение для внесения следующих изменений:

  1. измените PATH_INFO, чтобы обработать префикс url.
  2. изменить 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, если вам нужно.

Это решение задано gist Larivact. APPLICATION_ROOT не для этой работы, хотя похоже, что это так. Это действительно запутанно.

25
ответ дан su27 17 August 2018 в 20:32
поделиться
  • 1
    Спасибо, что добавил этот ответ. Пробовал другие решения, размещенные здесь, но это единственный, который работал на меня. A +++ Я развернута в IIS с помощью wfastcgi.py – sytech 20 April 2016 в 01:12
  • 2
    "APPLICATION_ROOT не для этого задания & quot; - вот где я ошибся. Я желаю, чтобы параметр Blueprint url_prefix и APPLICATION_ROOT были объединены по умолчанию, так что у меня могли быть URL-адреса области APPLICATION_ROOT для всего приложения, а url_prefix - URL-адреса в APPLICATION_ROOT только для отдельной схемы , Вздох – Monkpit 18 May 2016 в 14:38
  • 3
    См. этот текст для примера того, что я пытался сделать, используя APPLICATION_ROOT. – Monkpit 18 May 2016 в 14:43
  • 4
    Если вы используете gunicorn, SCRIPT_NAME уже поддерживается. Установите его как переменную среды или передайте его как http-заголовок: docs.gunicorn.org/en/stable/faq.html – blurrcat 27 December 2017 в 07:15
1
ответ дан Julian Camilleri 29 October 2018 в 19:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: