Un modo per aggirare questo è di imbrogliare l'algoritmo di ordinamento delle regole spoofing il metodo match_compare_key()
della regola registrata.Nota che questo hack funziona solo con le rotte che sono state registrate direttamente con app.route()
(l'oggetto Flask), non con Blueprints. Le rotte dei progetti vengono aggiunte all'url globale solo se la registrazione del modello viene eseguita sull'app principale, rendendo difficile la modifica delle regole generate.
# an ordinary route
@app.route('/<var1>/<var2>/<var3>')
def some_view(var1, var2, var3):
pass
# let's find the rule that was just generated
rule = app.url_map._rules[-1]
# we create some comparison keys:
# increase probability that the rule will be near or at the top
top_compare_key = False, -100, [(-2, 0)]
# increase probability that the rule will be near or at the bottom
bottom_compare_key = True, 100, [(2, 0)]
# rig rule.match_compare_key() to return the spoofed compare_key
rule.match_compare_key = lambda: top_compare_key
Si noti che in questo caso la funzione di spoofing risultante non è associata all'oggetto rule. Pertanto, alla chiamata rule.match_compare_key()
, la funzione non riceve un argomento self
. Se si desidera associare la funzione correttamente, fare questo, invece:
spoof = lambda self: top_compare_key
rule.match_compare_key = spoof.__get__(rule, type(rule))
possiamo generalizzare quanto sopra con un decoratore
def weighted_route(*args, **kwargs):
def decorator(view_func):
compare_key = kwargs.pop('compare_key', None)
# register view_func with route
app.route(*args, **kwargs)(view_func)
if compare_key is not None:
rule = app.url_map._rules[-1]
rule.match_compare_key = lambda: compare_key
return view_func
return decorator
# can be used like @app.route(). To weight the rule, just provide
# the `compare_key` param.
@weighted_route('/<var1>/<var2>/<var3>', compare_key=bottom_compare_key)
def some_view(var1, var2, var3):
pass
Lo stesso trucco implementato come un contesto manager.
import contextlib
@contextlib.contextmanager
def weighted_route(compare_key=None):
yield
if compare_key is not None:
rule = app.url_map._rules[-1]
rule.match_compare_key = lambda: compare_key
# and to use
with weighted_route(compare_key):
@app.route('/<var1>/<var2>/<var3>')
def some_view(var1, var2, var3):
pass
Un paio di interessante si legge: [sistema di routing Flask] (http://flask.pocoo.org/docs/design/#the-routing-system) e [Werkzeug di routing] (http: // Werkzeug .pocoo.org/docs/routing/# modulo-werkzeug.routing). Potrebbe anche voler esplorare usando [Blueprints] (http://flask.pocoo.org/docs/blueprints/) –