2015-10-07 8 views
8

Hintergrund

der Reverse Lassen Sie sagen, ich ein URL-Muster mit den Parametern, die mich zu einer Ansicht in django verbinden werden:Django - Namen von Parametern erhalten benötigt, um url

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

Und lassen sagen, ich habe eine thing und ein feature:

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

t_name = thing.name 
f_name = feature.name 

Jetzt Django gibt mir die unglaubliche Fähigkeit, eine uRL zu erhalten, die mich auf einer Seite zu einem bestimmten Merkmale eines bestimmten t gewidmet bringt Hing. Ich kann das in etwa so:

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

Frage

Jetzt habe ich in eine Situation gestolpert, die ich brauche, um spezifisch zu adressieren. Ich bin nicht auf der Suche für eine Abhilfe - Ich suche das folgende Problem zu lösen:

Bei einer URL name, wie kann ich die Liste der kwarg Argument Namen erhalten benötigt, um diese URL zu umkehren?

Ich bin auf der Suche nach der Funktion get_kwarg_names_for_url. Es verhält sich wie folgt:

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

url_kwarg_names ist jetzt die Liste der jedes Keyword ich Djangos reverse Funktion zu liefern, um benötigen die URL zu umkehren namens "thing_feature".

Jede Hilfe wird geschätzt!

Lösung

Basierend auf knbk Antwort ich in der Lage war, mit der folgenden Lösung zu kommen:

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

Ich ging gerade ein Kaninchenloch von: die URL umkehren, die URL zu einem urlpattern zusammenbringen, den urlpattern Regex kompilieren und den 'groupindex' der Regex überprüfen ... Ich muss etwas hier vermissen. – Monkpit

+1

Ein Problem ist, dass Sie die URL nicht umkehren können, bevor Sie die erforderlichen URL-Parameternamen bereits kennen - django wird einen Fehler für 'reverse ('thing_feature')' auslösen, da die benötigten Kwargs fehlen! –

+0

Sie können dies versuchen http://StackOverflow.com/a/1275601 Ich habe mich hier versucht, und mit '.items()' stattdessen, gibt es eine schöne Liste von Tupeln, die die Kwargs hat. Du musst tiefer gehen scheint ein guter Anfang zu sein, leider gehe ich jetzt nach Hause und kann nicht tiefer gehen. – Tiago

Antwort

2

ich mit einer fairen Warnung beginnen werde: dies nicht möglich ist, die öffentliche API. Darüber hinaus arbeite ich aktiv daran, den URL-Dispatcher für 1.10 neu zu schreiben, so dass diese Methode wahrscheinlich zu diesem Zeitpunkt nicht mehr funktioniert.

Zuerst müssen Sie das richtige RegexURLResolver bekommen.Wenn die Ansicht nicht in einem Namespace ist, können Sie die reverse_dict verwenden, um eine Liste der Möglichkeiten zu bekommen, und die kwargs extrahieren:

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 

Da View- Namen mehrere Muster mit unterschiedlichen kwargs haben kann (obwohl man sich wünschen um dies für deine eigene Gesundheit zu vermeiden), wird dies eine Liste aller möglichen Kwargs zurückgeben. Normalerweise wären die verschiedenen Sätze die erforderlichen Kwargs auf der einen Seite und erforderten + optionale Kwargs auf der anderen Seite.

ich nicht getestet haben, aber wenn es nicht, dass Sie ein wenig in resolver.reverse_dict wühlen können nicht arbeiten, um die genaue Einzelheiten zu erfahren. Es wurde nicht genau auf Benutzerfreundlichkeit ausgelegt.

+0

Sie sind ein Wilder. Ihr Code funktioniert nicht direkt, aber es gab mir mehr als genug Informationen, um es funktionsfähig zu machen. Ich mache mir auch keine Gedanken über Url-Regexes, die zu mehreren Kwarg-Arrangements führen. Meine Frage wurde aktualisiert, um zu zeigen, was am Ende funktioniert hat. –

+0

p.s. Es klingt, als wärst du einer der Django-Autoren? –

+0

@GershomMaes Ich bin ein Mitwirkender, nicht Teil des Kernteams obwohl;) – knbk

0

Sie sollten diesen in der Lage sein zu tun, mit einem resolve()

Aus dem Text & Tabellen:

Ein ResolverMatch-Objekt kann dann abgefragt werden, um Informationen über die URL p bereitzustellen attern, die eine URL entspricht:

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

spezifisch für Ihren Beispielcode:

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

Sie können den URL-Namen nicht an "resolve" übergeben. – ozgur

+0

@ozgur basierend auf Ihrem Kommentar aktualisiert. –