Tengo un prefijo que quiero agregar a cada ruta. Ahora puedo añadir una constante de la ruta en cada definición. Hay una manera de hacer esto automáticamente?

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"

OriginalEl autor Evan Hahn | 2013-09-23

9 Comentarios

  1. 58

    La respuesta depende de cómo están al servicio de esta aplicación.

    Sub-montado en el interior de otro WSGI contenedor

    Suponiendo que se va a ejecutar esta aplicación dentro de un WSGI contenedor (mod_wsgi, uwsgi, gunicorn, etc); necesitamos realmente el monte, en ese prefijo la aplicación como una sub-parte de que WSGI contenedor (algo que habla de WSGI va a hacer) y para establecer su APPLICATION_ROOT config valor a su prefijo:

    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/"

    Configuración de la APPLICATION_ROOT config valor simplemente limitar el Matraz de la cookie de sesión para que el prefijo de URL. Todo lo demás será manejado automáticamente por usted por Frasco y Werkzeug excelente WSGI capacidades de manejo.

    Un ejemplo de correctamente sub-montaje de su aplicación

    Si usted no está seguro de lo que el primer párrafo significa, echa un vistazo a este ejemplo de aplicación con Frasco montado en el interior de la misma:

    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)

    De proxy de las solicitudes para la aplicación

    Si, por el contrario, se estará ejecutando su Frasco de aplicación en la raíz de su WSGI contenedor y proxy solicitudes (por ejemplo, si es FastCGI d a, o si nginx es proxy_pass-ción de las solicitudes para un sub-punto final a su stand-alone uwsgi /gevent servidor, a continuación, usted puede:

    • El uso de un Modelo, como Miguel señala en su respuesta.
    • o utilizar el DispatcherMiddleware de werkzeug (o el PrefixMiddleware de su27 la respuesta) a la sub-montaje de su aplicación en el stand-alone WSGI servidor que está usando. (Ver Un ejemplo de correctamente sub-montaje de su aplicación anteriormente para el código a utilizar).
    buscando en flask.Flask#create_url_adapter y werkzeug.routing.Map#bind_to_environ parece trabajo – cómo se estaban ejecutando el código? (La aplicación que realmente necesita para ser montado en la sub-ruta en un WSGI medio ambiente para url_for para devolver el valor esperado.)
    Me encontré exactamente lo que usted escribió, pero añadió app = Matraz(nombre) y de la aplicación.ejecutar(debug=True)
    ese es el problema, tendrás que montar la aplicación como una sub-parte de una aplicación más grande (algo que habla de WSGI va a hacer). He batida de un ejemplo gist y actualizado mi respuesta para dejar claro que estoy asumiendo un sub-montado WSGI medio ambiente, no es un stand-alone WSGI entorno detrás de un proxy, que es sólo el reenvío de sub-ruta de las solicitudes.
    Esto funciona, el uso de la DispatcherMiddleware enfoque, cuando se ejecuta el frasco por sí mismo. No pueden parecer para que funcione cuando se está detrás de Gunicorn.
    estás ejecutando parent_app o simplemente app a través de su Gunicorn de configuración? (Usted necesidad de centrarse en la parent_app como su WSGI de la aplicación).

    OriginalEl autor Sean Vieira

  2. 68

    Usted puede poner sus rutas en un plano:

    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"

    A continuación, registrar el modelo con la aplicación el uso de un prefijo:

    app = Flask(__name__)
    app.register_blueprint(bp, url_prefix='/abc/123')
    Hola Miguel; ¿sabe usted la diferencia entre el registro de un url_prefix para un proyecto como el que usted hizo a continuación con app.register_blueprint y entre el registro que al crear el Modelo de objetos de arriba, pasando url_prefix='/abc/123? Gracias!
    La diferencia es que al tener el prefijo de URL en el register_blueprint llamada le da a la aplicación de la libertad para «montar» el plan en cualquier lugar que desee, o incluso montar el mismo modelo varias veces en diferentes Direcciones. Si pones el prefijo en el plan en sí hará que sea más fácil para la aplicación, pero tiene menos flexibilidad.
    Gracias!! Eso es muy útil. Yo estaba confundido por la aparente redundancia, pero veo que el trade-off entre las dos opciones.
    Y en realidad, nunca he intentado esto, pero es probable que usted puede combinar prefijos de dirección URL, tanto en el diseño y la aplicación, con la aplicación del prefijo de puño, seguido por el modelo prefijo.
    Tenga en cuenta que es necesario registrar el modelo después en el modelo.ruta decorado funciones.

    OriginalEl autor Miguel

  3. 26

    Debe tener en cuenta que la APPLICATION_ROOT NO es para este propósito.

    Todo lo que tienes que hacer es escribir un middleware para realizar los siguientes cambios:

    1. modificar PATH_INFO para manejar el prefijo de url.
    2. modificar SCRIPT_NAME para generar el prefijo de url.

    Como este:

    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()]

    Envoltura de su aplicación con el middleware, como este:

    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)

    Visita http://localhost:9010/foo/bar,

    Obtendrá el resultado correcto: The URL for this page is /foo/bar

    Y no se olvide de establecer el dominio de la cookie, si es necesario.

    Esta solución está dada por Larivact del gist. El APPLICATION_ROOT no es para este trabajo, a pesar de que parece ser. Es algo muy confuso.

    Gracias por la adición de esta respuesta. Tratado de las otras soluciones publicado aquí, pero este es el único que trabajó para mí. A+++estoy implementado en el uso de IIS wfastcgi.py
    «El APPLICATION_ROOT no es para este trabajo» – aquí es donde me iba mal. Deseo Blueprint‘s url_prefix parámetro y APPLICATION_ROOT fueron combinados por defecto, por lo que podría haber APPLICATION_ROOT ámbito de url para toda la aplicación, y url_prefix ámbito url dentro de APPLICATION_ROOT sólo para el individuo plan. Suspiro
    Consulte esta esencia para ver un ejemplo de lo que yo estaba tratando de hacer uso de APPLICATION_ROOT.
    Si usted está usando gunicorn, SCRIPT_NAME ya está soportado. Se establece como una variable de entorno o pasar a través de un encabezado http: docs.gunicorn.org/en/stable/faq.html

    OriginalEl autor su27

  4. 7

    Esto es más de un python respuesta de un Matraz/werkzeug respuesta; pero es muy simple y funciona.

    Si, como yo, usted quiere que su configuración de la aplicación (se puede cargar desde un .ini archivo) para que también contienen el prefijo de su Frasco de la aplicación (por lo tanto, no tienen el valor establecido durante la implementación, pero durante el tiempo de ejecución), se puede optar por la siguiente:

    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

    Podría decirse que esto es algo hackish y se basa en el hecho de que el Frasco función de ruta requiere un route como primer argumento posicional.

    Se puede utilizar como esto:

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

    PD: de nada vale que es posible utilizar una variable en el prefijo (por ejemplo mediante el establecimiento de /<prefix>) y, a continuación, el proceso de este prefijo en las funciones que puedes decorar con tus @app.route(...). Si lo hace, es obvio que tiene que declarar la prefix parámetro en la función decorado(s). Además, es posible que desee comprobar los presentados prefijo contra algunas reglas, y devolver un mensaje de error 404 si la comprobación falla. Con el fin de evitar un mensaje de error 404 personalizada re-aplicación, por favor from werkzeug.exceptions import NotFound y, a continuación, raise NotFound() si la comprobación falla.

    No puede decir que «enfermos» que quieres decir. Yo creo que ambos se aplican.

    OriginalEl autor 7heo.tk

  5. 3

    Por lo tanto, creo que una respuesta válida a esta es: el prefijo debe ser configurado en el servidor de aplicación que se utiliza cuando el desarrollo se ha completado. Apache, nginx, etc.

    Sin embargo, si a usted le gustaría trabajar durante el desarrollo mientras se ejecuta el Matraz de aplicación en la depuración, echa un vistazo a esta esencia.

    Matraz del DispatcherMiddleware al rescate!

    Voy a copiar el código aquí para la posteridad:

    "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)

    Ahora, cuando se ejecuta el código anterior como un solo Frasco de aplicación, http://localhost:5000/spam/ mostrará Hello, world!.

    En un comentario en otra respuesta, me expresó que he querido hacer algo como esto:

    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/

    La aplicación de DispatcherMiddleware a mi ejemplo inventado:

    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/
    «Así que creo que una respuesta válida a esta es: el prefijo debe ser configurado en el servidor de aplicación que se utiliza cuando el desarrollo se ha completado. Apache, nginx, etc.» El problema está en redirige; si usted tiene un prefijo y no se configura en el Frasco, luego, cuando se vuelve a dirigir en lugar de ir a /yourprefix/path/to/url apenas va a la /ruta/al/url. Es allí una manera de establecer, en nginx o Apache, cuál es el prefijo tiene que ser?
    La manera en que lo haría probablemente hacer esto es usar una configuración de la herramienta de administración como puppet o chef, y establecer el prefijo de allí y, a continuación, la herramienta propagar el cambio en los archivos de configuración donde necesita ir. No voy a incluso fingir que sé de qué estoy hablando para apache o nginx. Desde esta pregunta/respuesta fue específicos para python, me animo a publicar su escenario como una cuestión separada. Si usted hace esto, siéntase libre para vincular a la pregunta aquí!

    OriginalEl autor Monkpit

  6. 1

    Necesitaba similar llamado «context-root». Yo lo hice en el fichero de configuración en /etc/httpd/conf.d/el uso de WSGIScriptAlias :

    myapp.conf:

    <VirtualHost *:80>
        WSGIScriptAlias /myapp /home/<myid>/myapp/wsgi.py
    
        <Directory /home/<myid>/myapp>
            Order deny,allow
            Allow from all
        </Directory>
    
    </VirtualHost>

    Así que ahora puedo acceder a mi aplicación como : http://localhost:5000/myapp

    Consulte la guía – http://modwsgi.readthedocs.io/en/develop/user-guides/quick-configuration-guide.html

    OriginalEl autor dganesh2002

  7. 1

    Otra forma completamente diferente es con puntos de montaje en uwsgi.

    De la doc sobre Hosting de múltiples aplicaciones en el mismo proceso (permalink).

    En su uwsgi.ini agregar

    [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

    Si usted no llame a su archivo main.py, usted necesita para cambiar tanto el mount y la module

    Su main.py podría tener este aspecto:

    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

    Y un nginx config (de nuevo por la exhaustividad):

    server {
      listen 80;
      server_name example.com
    
      location /foo {
        include uwsgi_params;
        uwsgi_pass unix:///temp/uwsgi.sock;
      }
    }

    Llamando ahora example.com/foo/bar mostrará /foo/bar como el que devuelve el matraz de la url_for('bar'), ya que se adapta automáticamente. De esa manera tus enlaces funcionan sin prefijo problemas.

    OriginalEl autor luckydonald

  8. 1

    Yo siempre prefiero usar el siguiente cuando se trata de la adición de un prefijo en todo el app:

    app = Flask(__name__, root_path='/operators')

    Limpio y claro.

    OriginalEl autor Julian Camilleri

  9. 0

    Mi solución en el matraz y aplicaciones PHP coexistir
    nginx y PHP5.6

    MANTENER el Frasco en la raíz y PHP en subdirectorios

    sudo vi /etc/php/5.6/fpm/php.ini
    Agregar 1 línea
    cgi.fix_pathinfo=0

    sudo vi /etc/php/5.6/fpm/piscina.d/www.conf
    escuchar = /ejecutar/php/php5.6-fpm.calcetín

    uwsgi

    sudo vi /etc/nginx/sites-available/default
    UTILICE ANIDADOS LUGARES para PHP y dejar que el MATRAZ de permanecer en la raíz

    LEER cuidadosamente
    https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms

    Necesitamos entender la ubicación de coincidencia
    (ninguno): Si no hay modificadores están presentes, la ubicación es interpretado como un prefijo de partido. Esto significa que la ubicación dada coincidirá con el comienzo de la URI de la solicitud para determinar una coincidencia.
    =: Si un signo igual se utiliza, este bloque se considera una coincidencia si el URI de la solicitud coincide exactamente con la ubicación dada.
    ~: Si una tilde modificador está presente, este sitio será interpretado como un caso sensible a la coincidencia de la expresión regular.
    ~*: Si una tilde y el asterisco modificador se utiliza, el bloque de ubicación será interpretado como un insensible a mayúsculas-coincidencia de la expresión regular.
    ^~: Si un quilate y tilde modificador está presente, y si este bloque es seleccionado como el mejor de la no-coincidencia de la expresión regular, de expresiones regulares no tendrá lugar.

    El orden es importante, de nginx la «ubicación» descripción:

    Para encontrar la ubicación de la coincidencia de una solicitud, nginx comprueba primero lugares definidos usando el prefijo cadenas (prefijo de ubicaciones). Entre ellos, la ubicación con la mayor coincidencia de prefijo es seleccionada en la memoria. A continuación, las expresiones regulares son revisadas, en el orden de su aparición en el archivo de configuración. La búsqueda de expresiones regulares termina en el primer partido, y la correspondiente configuración se utiliza. Si no coincidan con una expresión regular que se encuentra a continuación, la configuración del prefijo de la ubicación recordado anteriormente se utiliza.

    Significa:

    Primera =. («el prefijo coincidente más largo» partido)
    Luego implícito. («el prefijo coincidente más largo» partido)
    Luego regex. (primer partido)

    OriginalEl autor Jayanta

Dejar respuesta

Please enter your comment!
Please enter your name here