¿Cómo uso url_for si mi método tiene múltiples anotaciones de ruta?

Así que tengo un método que es accesible por múltiples rutas:

@app.route("/canonical/path/") @app.route("/alternate/path/") def foo(): return "hi!" 

Ahora, ¿cómo puedo llamar a url_for("foo") y saber que obtendré la primera ruta?

De acuerdo. Me costó profundizar en el código werkzeug.routing y flask.helpers.url_for , pero ya lo descubrí. Acaba de cambiar el endpoint de la ruta (en otras palabras, nombre su ruta)

 @app.route("/canonical/path/", endpoint="foo-canonical") @app.route("/alternate/path/") def foo(): return "hi!" @app.route("/wheee") def bar(): return "canonical path is %s, alternative is %s" % (url_for("foo-canonical"), url_for("foo")) 

Producirá

la ruta canónica es / canonical / ruta /, la alternativa es / alternate / ruta /

Hay un inconveniente de este enfoque. Flask siempre vincula la última ruta definida al punto final definido implícitamente ( foo en su código). ¿Adivina qué pasa si redefinís el punto final? Todos tus url_for('old_endpoint') lanzarán werkzeug.routing.BuildError . Entonces, supongo que la solución correcta para todo el problema es definir la ruta canónica, la última y la alternativa de nombre :

 """ since url_for('foo') will be used for canonical path we don't have other options rather then defining an endpoint for alternative path, so we can use it with url_for """ @app.route('/alternative/path', endpoint='foo-alternative') """ we dont wanna mess with the endpoint here - we want url_for('foo') to be pointing to the canonical path """ @app.route('/canonical/path') def foo(): pass @app.route('/wheee') def bar(): return "canonical path is %s, alternative is %s" % (url_for("foo"), url_for("foo-alternative")) 

Las reglas en el matraz son únicas. Si define la misma URL absoluta para la misma función, de forma predeterminada se producirá un conflicto porque está haciendo algo que le impedimos hacer ya que, desde nuestra perspectiva, eso es incorrecto.

Hay una razón por la que desearía tener más de una URL para el mismo punto final y es la compatibilidad hacia atrás con una regla que existía en el pasado. Desde WZ0.8 y Flask 0.8 puede especificar explícitamente un alias para una ruta:

 @app.route('/') @app.route('/index.html', alias=True) def index(): return ... 

En este caso, si el usuario solicita /index.html Flask emitirá automáticamente un redireccionamiento permanente a solo / .

Eso no significa que una función no pueda estar vinculada a más de una url, pero en este caso necesitaría cambiar el punto final:

 @app.route('/') def index(): ... app.add_url_rule('/index.html', view_func=index, endpoint='alt_index') 

O alternativamente:

 @app.route('/') @app.route('/index.html', endpoint='alt_index') def index(): ... 

En este caso, puede definir una vista por segunda vez con un nombre diferente. Sin embargo, esto es algo que generalmente se quiere evitar porque entonces la función de vista tendría que revisar request.endpoint para ver qué se llama. En su lugar, mejor hacer algo como esto:

 @app.route('/') def index(): return _index(alt=False) @app.route('/index.html') def alt_index(): return _index(alt=True) def _index(alt): ... 

En ambos casos, la generación de URL es url_for('index') o url_for('alt_index') .

También puede hacer esto en el nivel del sistema de enrutamiento:

 @app.route('/', defaults={'alt': False}) @app.route('/index.html', defaults={'alt': True}) def index(alt): ... 

En este caso, la generación de url es url_for('index', alt=True) o url_for('index', alt=False) .

Además, para aquellos que utilizan una ruta de captura total construida con variables: Flask creará correctamente la ruta de URL si url_for pasa un diccionario que contiene las variables.

Por ejemplo…

app.py:

 app.route('/') app.route('//') def catch_all(pattern1, pattern2=None): return render_template('template.html', p1=pattern1, p2=pattern2) app.route('/test') def test_routing: args = {'pattern1': 'Posts', 'pattern2': 'create'} return render_template('test.html', args=args) 

test.html:

 click here 

Cuando haga clic en el enlace ‘haga clic aquí’, se le dirigirá a la ruta ‘Publicaciones / crear’.