2015-10-07 14 views
8

Sfondo

Diciamo che ho un modello di URL con i parametri che mi farà saltare a una vista in django:Django - ottenere i nomi di parametri necessari per invertire url

url(
    r'^things/(?P<thing_name>\w+)/features/(?P<feature_name>\w+)$', 
    views.thingFeature, 
    name='thing_feature' 
), 

e permette di dire che ho un thing e un feature:

thing = Thing.objects.get(.....) 
feature = thing.feature_set.first() 

t_name = thing.name 
f_name = feature.name 

Ora Django mi dà la straordinaria capacità di ottenere un URL che mi porta a una pagina dedicata ad una caratteristica specifica di una specifica t Hing. Posso farlo in questo modo:

from django.core.urlresolvers import reverse 
url = reverse('thing_feature', thing_name=t_name, feature_name=f_name) 
# url == '/things/thing2/features/left-arm' 

Domanda

Ora mi hai inciampato in una situazione che ho bisogno di affrontare specificamente. Io non sto cercando una soluzione - Sto cercando di risolvere il seguente problema:

Data di name un URL, come faccio ad ottenere l'elenco dei nomi degli argomenti kwarg necessarie per invertire tale URL?

Sto cercando la funzione get_kwarg_names_for_url. Si comporta in questo modo:

url_kwarg_names = get_kwarg_names_for_url('thing_feature') 
# url_kwarg_names == ['thing_name', 'feature_name'] 

url_kwarg_names è ora la lista di ogni parola chiave che ho bisogno di fornire alla funzione di Django reverse al fine di invertire l'url di nome "thing_feature".

Qualsiasi aiuto è apprezzato!

Soluzione

in base alla risposta del knbk sono stato in grado di venire con la seguente soluzione:

def get_kwarg_names_for_url(url_name): 
    resolver = get_resolver(get_urlconf()) 
    reverse_data = resolver.reverse_dict[url_name] 

    pattern_list = reverse_data[0] 

    ''' 
    Need to specify the 1st pattern because url regexes can 
    potentially have multiple kwarg arrangments - this function does 
    not take this possibility into account. 
    ''' 
    first_pattern = pattern_list[0] 

    ''' 
    `first_pattern` is now of the form `(url_string, kwarg_list)` - 
    all we are interested in is the 2nd value. 
    ''' 
    return first_pattern[1] 
+0

Sono appena sceso in una tana del coniglio di: invertire l'url, abbinare l'url a un urlpattern, compilare la regex urlpattern e ispezionare il 'groupindex' della regex ... Devo mancare qualcosa qui. – Monkpit

+1

Un problema è che non è possibile invertire l'url prima di conoscere già i nomi dei parametri url richiesti - django genererà un errore per 'reverse ('thing_feature')' perché mancano i kwarg necessari! –

+0

Puoi provare questo http://stackoverflow.com/a/1275601 Mi sono cimentato qui, e usando '.items()' invece, restituisce una bella lista di tuple che contiene i kwargs. Devi andare più in profondità sembra essere un buon inizio, sfortunatamente sto andando a casa ora e non può andare più in profondità. – Tiago

risposta

2

Comincerò con un avvertimento giusto: questo non è possibile utilizzare l'API pubblica. Inoltre, sto lavorando attivamente per riscrivere il dispatcher dell'URL per 1.10, quindi questo metodo probabilmente si interromperà a quell'ora.

In primo luogo, è necessario ottenere il diritto RegexURLResolver.Se la vista non è in uno spazio dei nomi, è possibile utilizzare il reverse_dict per ottenere un elenco di possibilità, ed estrarre i kwargs:

def get_kwargs(view_name): 
    resolver = urlresolvers.get_resolver() 
    patterns = resolver.reverse_dict.getlist(view_name) 
    kwargs = [] 
    for possibility, pattern, defaults in patterns: 
     for result, params in possibility: 
      kwargs.append(params) 
    return kwargs 

Dal momento che un nome di vista può avere più modelli con diverse kwargs (anche se ci si vuole per evitare ciò per la tua sanità mentale, questo restituirà una lista di ogni set di kwarg possibili. Di solito i diversi set sarebbero i kwarg richiesti su un lato e kwargs obbligatori + facoltativi sull'altro lato.

Non ho provato questo, ma se non funziona è possibile scavare in giro per resolver.reverse_dict per un po 'per scoprire le specifiche esatte. Non è stato progettato esattamente con l'usabilità in mente.

+0

Lei signore è un selvaggio. Il tuo codice non funziona direttamente, ma mi ha dato più informazioni sufficienti per renderlo funzionale. Inoltre, non sono preoccupato per le regex dell'url risultanti in più accordi di kwarg. Aggiornato la mia domanda per riflettere cosa ha funzionato alla fine. –

+0

p.s. Sembra che tu sia uno degli autori di Django? –

+0

@GershomMaes Sono un contributore, non parte del core team;) – knbk

0

si dovrebbe essere in grado di fare questo con un resolve()

dalla documentazione:

Un oggetto ResolverMatch può quindi essere interrogato per fornire informazioni sull'URL p attern che corrisponde a un URL:

func, args, kwargs = resolve('/some/path/')

specifico per il vostro codice di esempio:

url = reverse('thing_feature') 
func, args, kwargs = resolve(url) 
# args == ['thing_name', 'feature_name'] 
+0

Non è possibile passare il nome dell'URL a 'resolve'. – ozgur

+0

@ozgur aggiornato in base al tuo commento. –

Problemi correlati