Jednym ze sposobów obejścia tego problemu jest oszukiwanie algorytmu sortowania reguł poprzez podszywanie się do zarejestrowanej reguły w metodzie match_compare_key()
.Zauważ, że ten hack działa tylko w przypadku tras, które zostały zarejestrowane bezpośrednio pod app.route()
(obiekt Flask), a nie w Blueprints. Trasy projektów są dodawane do globalnej mapy URL tylko po zarejestrowaniu projektu w głównej aplikacji, co utrudnia modyfikowanie wygenerowanych reguł.
# 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
Należy zauważyć, że w takim przypadku wynikowa funkcja spoofowania nie jest powiązana z obiektem reguły. Dlatego po wywołaniu rule.match_compare_key()
funkcja nie otrzymuje argumentu self
. Jeśli chcesz powiązać funkcję prawidłowo to zrobić w zamian:
spoof = lambda self: top_compare_key
rule.match_compare_key = spoof.__get__(rule, type(rule))
Możemy uogólnić powyższe z dekorator
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
To samo technikę realizowane jako kierownik kontekstowego.
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
kilka interesujących brzmi: [System routingu Kolba] (http://flask.pocoo.org/docs/design/#the-routing-system) i [Werkzeug routing] (http: // Werkzeug .pocoo.org/docs/routing/# module-werkzeug.routing). Może też lubię odkrywać za pomocą [Blueprints] (http://flask.pocoo.org/docs/blueprints/) –