2013-10-02 10 views
8

Korzystam z Flask i Flask-RESTful do zbudowania interfejsu API REST. W ramach tego interfejsu API niektóre z moich zasobów zawierają relacje URL-i z innymi zasobami.Szukam odwrotności adresu url_for w Flask

Podczas wykonywania zapytań POST do tych zasobów, stwierdzam, że potrzebuję odwrotności funkcji url_for() Flask, aby przeanalizować przychodzący URL.

Na przykład, POST do https://www.example.com/buildings może zawierać następujące json:

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

chciałbym analizować identyfikator z owner i tenant stosując następującą trasę:

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

Czy istnieje wygodnym sposobem na zrobienie tego w Flask lub Werkzueg, czy powinienem sam przetworzyć adres URL? Byłoby miło móc ponownie wykorzystać zdefiniowaną już trasę ...

Znalazłem this post, ale nie wydaje się, aby opisać, jak to zrobić poza żądaniem.

+1

Może szukasz [kontekst żądania testowego] (http://dormousehole.readthedocs.org/en/latest/api.html#flask.Flask.test_request_context), który mógłby zostać użyty do utworzenia 'RequestContext'. –

Odpowiedz

3

Używam funkcji poniżej route_from:

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) 

Napisałem to patrząc na realizację url_for i odwrócenie go.

Argumentem url może być pełny adres URL lub tylko część informacji o ścieżce. Wartość zwracana jest krotką z nazwą punktu końcowego i dict z argumentami.

Nota prawna: Nie testowałem tego intensywnie. Planowałem ostatecznie przesłać go jako żądanie ściągnięcia, ale nigdy nie wydaje mi się, aby go w pełni przetestować i napisać kilka testów jednostkowych. Jeśli to nie działa, daj mi znać!

9

Najprostszy sposób utworzyć testowy kontekst życzenie (dzięki Leon Młode):

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

Ale cały sens pod maską tworzenia kontekstu żądanie:

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) 

Jeśli żaden protokół wyboru powód i host możesz utworzyć specjalną metodę dopasowania:

from functools import partial 

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

i używać go bez protokołu i gospodarz:

owner_url_rule, owner_view_args = match('/users/21414512') 
tenant_url_rule, tenant_view_args = match('/users/16324642') 
Powiązane problemy