2013-10-02 7 views
8

Ich verwende Flask und Flask-RESTful, um eine REST-API zu erstellen. Innerhalb dieser API enthalten einige meiner Ressourcen URL-Beziehungen zu anderen Ressourcen.Inverse von url_for in Flask suchen

Beim Ausführen von POST-Anfragen an diese Ressourcen finde ich, dass ich die umgekehrte von Flasks url_for() -Funktion brauche, um die eingehende URL zu analysieren.

Zum Beispiel kann ein POST https://www.example.com/buildings kann folgende json enthalten:

{ 
    "address": "123 Lyall St", 
    ... 
    "owner": { 
     "href": "https://www.example.com/users/21414512" 
    }, 
    "tenant": { 
     "href": "https://www.example.com/users/16324642" 
    }, 
} 

Ich möchte die ID aus owner und tenant mit dem folgenden Weg analysieren:

"https://www.example.com/users/<int:id>" 

Gibt es Eine praktische Möglichkeit, dies in Flask oder Werkzueg zu tun oder soll ich die URL selbst analysieren? Es wäre schön, die bereits definierte Route wiederverwenden zu können ...

Ich habe this Post gefunden, aber es scheint nicht zu beschreiben, wie man es außerhalb einer Anfrage macht.

+1

Vielleicht suchen Sie nach [test request context] (http://dormousehole.readthedocs.org/en/latest/api.html#flask.Flask.test_request_context), mit dem ein 'RequestContext' erzeugt werden könnte. –

Antwort

3

Ich benutze die route_from Funktion unten:

from flask.globals import _app_ctx_stack, _request_ctx_stack 
from werkzeug.urls import url_parse 

def route_from(url, method = None): 
    appctx = _app_ctx_stack.top 
    reqctx = _request_ctx_stack.top 
    if appctx is None: 
     raise RuntimeError('Attempted to match a URL without the ' 
          'application context being pushed. This has to be ' 
          'executed when application context is available.') 

    if reqctx is not None: 
     url_adapter = reqctx.url_adapter 
    else: 
     url_adapter = appctx.url_adapter 
     if url_adapter is None: 
      raise RuntimeError('Application was not able to create a URL ' 
           'adapter for request independent URL matching. ' 
           'You might be able to fix this by setting ' 
           'the SERVER_NAME config variable.') 
    parsed_url = url_parse(url) 
    if parsed_url.netloc is not "" and parsed_url.netloc != url_adapter.server_name: 
     raise NotFound() 
    return url_adapter.match(parsed_url.path, method) 

ich diese bei der Umsetzung von url_for indem Sie schrieb und es umgekehrt wird. Das url Argument kann eine vollständige URL oder nur der Pfadinfoabschnitt sein. Der Rückgabewert ist ein Tupel mit dem Endpunktnamen und einem dict mit den Argumenten.

Haftungsausschluss: Ich habe es nicht ausgiebig getestet. Ich plante, es schließlich als Pull-Anforderung einzureichen, aber ich bin nie dazu gekommen, es vollständig zu testen und einige Komponententests zu schreiben. Wenn es nicht für Sie funktioniert, lassen Sie es mich wissen!

9

Der einfachste Weg Testanforderungskontext (dank Leon Junge) erstellen:

with app.test_request_context(YOUR_URL) as request_ctx: 
    url_rule = request_ctx.request.url_rule 

Aber alle Sinne unter der Motorhaube zu schaffen Anforderungskontext:

from flask.testing import make_test_environ_builder 

builder = make_test_environ_builder(app, YOUR_URL) 
environ = builder.get_environ() 
url_adapter = app.url_map.bind_to_environ(environ) 
url_rule, view_args = url_adapter.match(return_rule=True) 

Wenn kein Protokoll Grund Prüfung und Host können Sie spezielle Match-Methode erstellen:

from functools import partial 

url_adapter = app.url_map.bind('localhost') 
match = partial(url_adapter.match, return_rule=True) 

und es verwenden, ohne Protokoll und host:

owner_url_rule, owner_view_args = match('/users/21414512') 
tenant_url_rule, tenant_view_args = match('/users/16324642') 
Verwandte Themen