2013-10-02 10 views
8

Sto usando Flask e Flask-RESTful per creare un'API REST. All'interno di questa API alcune delle mie risorse contengono relazioni url con altre risorse.Ricerca inversa di url_for in Flask

Quando si eseguono richieste POST a queste risorse, sto trovando che ho bisogno dell'inverso della funzione url_for() di Flask per analizzare l'url in entrata.

Per esempio, un post per https://www.example.com/buildings può contenere i seguenti JSON:

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

Vorrei analizzare l'id di owner e tenant utilizzando il seguente percorso:

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

C'è un modo conveniente per farlo in Flask o Werkzueg o dovrei solo analizzare l'url da solo? Sarebbe bello poter riutilizzare il percorso già definito ...

Ho trovato this post ma non sembra descrivere come farlo al di fuori di una richiesta.

+1

Forse stai cercando [contesto richiesta test] (http://dormousehole.readthedocs.org/en/latest/api.html#flask.Flask.test_request_context), che potrebbe essere utilizzato per creare un 'RequestContext'. –

risposta

3

a utilizzare la funzione route_from di seguito:

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) 

Ho scritto questo, cercando in l'attuazione di url_for e invertire la tendenza.

L'argomento url può essere un URL completo o solo la porzione di informazioni sul percorso. Il valore restituito è una tupla con il nome dell'endpoint e uno dict con gli argomenti.

Disclaimer: Non l'ho testato estesamente. Avevo intenzione di inviarlo come richiesta di pull, ma non mi sembra di andare in giro per testarlo completamente e scrivere alcuni test unitari. Se non funziona per te, fammi sapere!

9

Il modo più semplice creare contesto richiesta di test (grazie Leon giovani):

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

Ma il senso sotto il cofano del contesto di richiesta creazione:

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) 

Se nessun protocollo ragione controllo e host è possibile creare un metodo di corrispondenza speciale:

from functools import partial 

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

e utilizzarlo senza il protocollo e host:

owner_url_rule, owner_view_args = match('/users/21414512') 
tenant_url_rule, tenant_view_args = match('/users/16324642') 
Problemi correlati