Jak uzyskać aktualną nazwę url za pomocą Django?

90

Muszę dynamicznie zbudować adres URL zgodnie z aktualnym adresem URL. Używanie {% url %}tagu to najłatwiejszy sposób, ale potrzebuję aktualnej nazwy adresu URL, aby dynamicznie wygenerować nowy.

Jak mogę uzyskać nazwę adresu URL dołączoną do urlconf, która prowadzi do bieżącego widoku?

EDYCJA: Wiem, że mogę ręcznie stworzyć adres URL, get_absolute_urlale wolałbym tego uniknąć, ponieważ jest to część wykładu i chciałbym zademonstrować tylko jeden sposób tworzenia adresów URL.

Uczniowie wiedzą, jak używać {% url %}. Wiedzą, że napotykają problem, kiedy muszą wygenerować bardziej kompletny adres URL na podstawie bieżącego. Najłatwiej jest użyć go {% url %}ponownie, z pewnymi zmianami. Ponieważ nazwaliśmy url, musimy wiedzieć, jak uzyskać nazwę adresu URL, który wywołał bieżący widok.

EDYCJA 2: innym przypadkiem użycia jest wyświetlanie części szablonu podstawowego w inny sposób w zależności od szablonu podstawowego. Są na to inne sposoby (używając CSS i {% block%}, ale czasami miło jest móc usunąć znacznik wpisu menu base.html, jeśli nazwa widoku pasuje do linku.

e-satis
źródło
6
Ciągle znajdowałem to pytanie, szukając sposobu na wyprowadzenie bieżącego, bezwzględnego adresu URL za pomocą tagu szablonu ... jeśli również tego szukasz, jest to:{{ request.get_full_path }}
Dolph

Odpowiedzi:

134

Nie wiem, jak długo ta funkcja była częścią Django, ale jak pokazuje poniższy artykuł , można to osiągnąć w następujący sposób:

   from django.core.urlresolvers import resolve
   current_url = resolve(request.path_info).url_name

Jeśli potrzebujesz tego w każdym szablonie, napisanie żądania szablonu może być odpowiednie.

Edycja: STOSOWANIE NOWEJ AKTUALIZACJI DJANGO

Po aktualnej aktualizacji Django:

Django 1.10 ( link )

Importowanie z django.core.urlresolversmodułu jest przestarzałe na rzecz nowej lokalizacji,django.urls

Django 2.0 ( łącze )

django.core.urlresolversModuł jest usuwany za jego nowej lokalizacji django.urls.

Tak więc właściwy sposób jest następujący:

from django.urls import resolve
current_url = resolve(request.path_info).url_name
Lukas Bünger
źródło
Czemu? O ile zrozumiałem twoje pytanie, istotną częścią było to, jak osiągnąć „Skoro nazwaliśmy url, musimy wiedzieć, jak uzyskać nazwę adresu URL, który wywołał bieżący widok”. ...
Lukas Bünger
1
Właściwie lukas, byłem zrzędliwy tego dnia i odrzuciłem twoją odpowiedź całkowicie arbitralnie. Przepraszam, bo to jest właściwie prawidłowa odpowiedź. zamierzam go edytować, aby był bardziej odrażający.
e-satis
8
resolve()nie można rozwiązać, jeśli przekażesz ciąg zapytania i po prostu podniesie 404. get_full_path()zwraca ścieżkę i ciąg zapytania. Będziesz musiał użyć resolve(request.path_info).
Czy Burak Çilingir
A jeśli to nie currentadres URL musi zostać rozwiązany, ale, powiedzmy, ten, do którego użytkownik ma przekierować? Jaki jest bardziej ogólny sposób osiągnięcia tego? Odpowiedź Conleya Owensa ma wskazówkę, ale wolałbym nie wymyślać koła na nowo, jeśli to koło już istnieje w Django pod maską.
Hassan Baig
Wydaje się, że to nie działa dla przetłumaczalnych adresów URL z i18n_patterns
guival
109

Począwszy od Django 1.5, dostęp do tego można uzyskać z obiektu żądania

    current_url = request.resolver_match.url_name

https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.resolver_match

Bharathwaaj
źródło
Kiedy umieściłem to w procesorze kontekstu, zadziałało, ale ten dziwny błąd pojawił się w konsoli:AttributeError: 'WSGIRequest' object has no attribute 'resolver_match'
fjsj
2
Element „resolver_match” jest dodawany do obiektu żądania dopiero po wywołaniu całego oprogramowania pośredniczącego żądania. Wtedy właśnie adresy URL są rozwiązywane. Możesz więc uzyskać dostęp tylko od widoku oprogramowania pośredniego. (funkcje process_view oprogramowania pośredniego). Nie będzie dostępny w funkcjach oprogramowania pośredniego żądań. (funkcje process_request oprogramowania pośredniego).
Bharathwaaj
.view_namejeśli potrzebujesz przestrzeni nazw
27

Dla tych, którzy używają przestrzeni nazw swoich wzorców adresów URL, możesz być zainteresowany nazwą adresu URL żądania w przestrzeni nazw. W tym przypadku Django nazwał go view_namezamiast tego.

request.resolver_match.view_name

# return: <namespace>:<url name>
Yeo
źródło
Dzięki, ale jest to w dużej mierze oszustwo wcześniejszej odpowiedzi @dariusza-niespodzianego, prawda? stackoverflow.com/a/31931833/1450294
Michael Scheper
5
Jeśli nie masz przestrzeni nazw, urls.pyto @ dariusz-niespodziany jest natychmiastowo dostępne reverse. Ale jeśli używasz przestrzeni nazw, resolver_match.url_namenie można jej bezpośrednio reverseużywać. Dlatego musisz samodzielnie dołączyć przestrzeń nazw. Więc zamiast robić to samemu, Django już ustawił .view_nameprzy inicjalizacji.
Yeo
15

Można to osiągnąć poprzez:

    request.resolver_match.url_name

Django> 1,8

niespodd
źródło
4

Wyjaśnienie pytania: „W widoku, jak uzyskać nazwę wzorca adresu URL, który na niego wskazuje, zakładając, że istnieje dokładnie jeden taki wzorzec adresu URL”.

Może to być pożądane z podanych powodów: z widoku chcemy DRY sposób uzyskać adres URL do tego samego widoku (nie chcemy znać naszej własnej nazwy wzorca adresu URL).

Krótka odpowiedź: nie jest wystarczająco proste, aby uczyć swoją klasę, ale może to być zabawne zajęcie dla Ciebie za godzinę lub dwie i zwymiotowanie na GitHubie.

Jeśli naprawdę chciałbyś to zrobić, musiałbyś podklasować RegexURLResolver i zmodyfikować metodę rozstrzygania, aby zwracała dopasowany wzorzec (z którego możesz pobrać nazwę wzorca) zamiast par widok i słowo kluczowe / wartość. http://code.djangoproject.com/browser/django/trunk/django/core/urlresolvers.py#L142

Następnie można utworzyć dekorator lub bardziej odpowiednie oprogramowanie pośredniczące, które używa tej podklasy do pobierania nazwy wzorca i przechowywania tej wartości gdzieś w żądaniu, aby widoki mogły z niej korzystać.

Jeśli naprawdę chcesz to zrobić i napotkasz kłopoty, daj mi znać, a prawdopodobnie pomogę.

Dla twojej klasy chciałbym po prostu zakodować na stałe nazwę wzoru w widoku lub szablonie. Uważam, że jest to akceptowalny sposób robienia tego.

Aktualizacja: Im więcej o tym myślę, tym bardziej odradzam próbę uzyskania nazwy urlpattern w widoku. Parametry urlpattern są dość niezależne od parametrów widoku, na który wskazują. Jeśli chcesz wskazać określony adres URL, musisz wiedzieć, jak działa wzorzec url, a nie tylko jak działa widok. Jeśli chcesz wiedzieć, jak działa wzorzec url, równie dobrze możesz znać jego nazwę.

Conley Owens
źródło
3

Po prostu spróbuj request.path. Spowoduje to wyświetlenie żądanej bieżącej ścieżki.

Abhishek Iyengar
źródło
1

To trochę niejasne z Twojego pytania, ale http://docs.djangoproject.com/en/dev/topics/http/urls/ prawdopodobnie wyjaśni, czego szukasz.

Szczególnie przydatna jest uwaga, jak Django przetwarza żądania:

Gdy użytkownik zażąda strony z witryny opartej na Django, jest to algorytm, który system stosuje, aby określić, który kod Pythona ma wykonać:

  1. Django określa główny moduł URLconf do użycia. Zwykle jest to wartość ustawienia ROOT_URLCONF, ale jeśli przychodzący obiekt HttpRequest ma atrybut o nazwie urlconf (ustawiany przez przetwarzanie żądania oprogramowania pośredniego), jego wartość zostanie użyta zamiast ustawienia ROOT_URLCONF.
  2. Django ładuje ten moduł Pythona i szuka zmiennej urlpatterns. Powinna to być lista Pythona w formacie zwróconym przez funkcję django.conf.urls.defaults.patterns ().
  3. Django przechodzi po kolei przez każdy wzorzec adresu URL i zatrzymuje się na pierwszym, który pasuje do żądanego adresu URL.
  4. Po dopasowaniu jednego z wyrażeń regularnych Django importuje i wywołuje podany widok, który jest prostą funkcją Pythona. Widok otrzymuje HttpRequest jako pierwszy argument i wszelkie wartości przechwycone w wyrażeniu regularnym jako pozostałe argumenty.

Jeśli szukasz pełnej ścieżki, możesz spróbować:

http://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.get_full_path

Mam nadzieję, że to pomoże - wskazuje, jak używać modułu URLconf i mam nadzieję, że pomoże ci wskazać właściwy kierunek.

Mark Mayo
źródło
Dzięki, ale wiem, że :-) Dodałem kilka wyjaśnień, aby uniknąć nieporozumień.
e-satis