Как получить текущее имя URL-адреса с помощью Django?

91

Мне нужно создать URL-адрес динамически в соответствии с текущим URL-адресом. Использование {% url %}тега - это самый простой способ сделать это, но мне нужно текущее имя URL-адреса, чтобы динамически генерировать новый.

Как я могу получить имя URL, прикрепленное к urlconf, ведущему к текущему представлению?

РЕДАКТИРОВАТЬ: Я знаю, что могу вручную вручную использовать URL-адрес, get_absolute_urlно я бы предпочел этого избежать, поскольку это часть лекции, и я хотел бы продемонстрировать только один способ создания URL-адресов.

Студенты умеют пользоваться {% url %}. Они знают, что сталкиваются с проблемой, когда им нужно сгенерировать более полный URL-адрес на основе текущего. Самый простой способ - использовать {% url %}снова, с некоторыми вариациями. Поскольку мы назвали URL-адрес, нам нужно знать, как получить имя URL-адреса, который вызывал текущее представление.

РЕДАКТИРОВАТЬ 2: другой вариант использования - отображать части базового шаблона по-разному в соответствии с базовым шаблоном. Есть и другие способы сделать это (используя CSS и {% block%}, но иногда просто приятно иметь возможность удалить тег из пункта меню base.html, если имя представления соответствует ссылке.

e-satis
источник
6
Я все время находил этот вопрос, пока искал способ вывести текущий абсолютный URL-адрес с помощью тега шаблона ... если вы тоже это ищете, это:{{ request.get_full_path }}
Dolph

Ответы:

134

Я не знаю, как долго эта функция была частью Django, но, как показано в следующей статье, в представлении ее можно реализовать следующим образом:

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

Если вам это нужно в каждом шаблоне, можно написать запрос шаблона.

Изменить: ПРИМЕНЕНИЕ НОВОГО ОБНОВЛЕНИЯ DJANGO

После текущего обновления Django:

Django 1.10 ( ссылка )

Импорт из django.core.urlresolversмодуля не рекомендуется в пользу его нового местоположения,django.urls

Django 2.0 ( ссылка )

django.core.urlresolversМодуль удаляется в пользу нового места, django.urls.

Таким образом, правильный способ сделать такой:

from django.urls import resolve
current_url = resolve(request.path_info).url_name
Лукас Бюнгер
источник
Зачем? Насколько я понял ваш вопрос, жизненно важной его частью было то, как добиться: «Поскольку мы назвали url-адрес, нам нужно знать, как получить имя URL-адреса, который вызывал текущее представление» ...
Лукас Bünger
1
На самом деле, Лукас, я был в тот день сварливым и совершенно произвольно отказался от твоего ответа. Прошу прощения, потому что это действительно правильный ответ. Я собираюсь отредактировать его, чтобы сделать его более ужасным.
e-satis
8
resolve()не может разрешиться, если вы передадите ему строку запроса и просто вызовете 404. get_full_path()возвращает путь и строку запроса. Вам нужно будет использовать resolve(request.path_info).
Кан Бурак Чилингир
Что, если currentнужно разрешить не URL-адрес, а, скажем, тот, на который пользователь собирается перенаправить? Какой более общий способ добиться этого? В ответе Конли Оуэнса есть ключ к разгадке, но я бы не стал изобретать велосипед, если это колесо уже существует в Django под капотом.
Hassan Baig
Похоже, это не работает для переводимых URL-адресов с i18n_patterns
guival
109

Начиная с Django 1.5, к нему можно получить доступ из объекта запроса

    current_url = request.resolver_match.url_name

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

Бхаратваадж
источник
Когда я поместил это в контекстный процессор, это сработало, но в консоли отображалась эта странная ошибка:AttributeError: 'WSGIRequest' object has no attribute 'resolver_match'
fjsj
2
«Resolver_match» добавляется к объекту запроса только после вызова всего промежуточного программного обеспечения запроса. Это когда URL-адреса разрешаются. Таким образом, вы можете получить доступ только к промежуточному программному обеспечению просмотра и далее. (функции process_view промежуточного программного обеспечения). Он не будет доступен в функциях промежуточного программного обеспечения запросов. (функции process_request промежуточного программного обеспечения).
Bharathwaaj
.view_nameесли вам нужно пространство имен
28

Для тех, кто использует свои шаблоны URL-адресов в пространстве имен, вас может заинтересовать имя URL-адреса запроса в пространстве имен. В данном случае это вызвал Django view_name.

request.resolver_match.view_name

# return: <namespace>:<url name>
Йео
источник
Спасибо, но это в значительной степени обман предыдущего ответа @dariusz-niespodziany, не так ли? stackoverflow.com/a/31931833/1450294
Майкл Шепер 06
5
Если вы не использовали пространство имен, urls.pyто @ dariusz-niespodziany можно сразу же reverseиспользовать. Но если вы используете пространство имен, resolver_match.url_nameэто невозможно напрямую reverse. Таким образом, вы должны сами добавить пространство имен. Итак, вместо того, чтобы делать это самостоятельно, Django уже установил .view_nameпри инициализации.
Yeo
15

Этого можно достичь с помощью:

    request.resolver_match.url_name

Django> 1.8

Niespodd
источник
4

Уточнение вопроса: «С точки зрения представления, как получить имя шаблона URL, указывающего на него, при условии, что существует ровно один такой шаблон URL».

Это может быть желательно по указанным причинам: изнутри представления нам нужен СУХИЙ способ получения URL-адреса того же представления (мы не хотим знать свое собственное имя urlpattern).

Краткий ответ: преподавать в классе не совсем просто, но, возможно, вам будет интересно сделать это через час или два и бросить на GitHub.

Если вы действительно хотите это сделать, вам придется создать подкласс RegexURLResolver и изменить метод разрешения, чтобы он возвращал совпадающий шаблон (из которого вы можете получить имя шаблона) вместо пар представление и ключевое слово / значение. http://code.djangoproject.com/browser/django/trunk/django/core/urlresolvers.py#L142

Затем вы можете создать декоратор или, возможно, более подходящее промежуточное программное обеспечение, которое использует этот подкласс для получения имени шаблона и сохранения этого значения где-нибудь в запросе, чтобы представления могли его использовать.

Если вы действительно хотите это сделать, и у вас возникнут проблемы, дайте мне знать, и я, вероятно, смогу помочь.

Для вашего класса я бы просто жестко запрограммировал имя шаблона в представлении или шаблоне. Я считаю, что это приемлемый способ сделать это.

Обновление: чем больше я думаю об этом, тем больше я не рекомендую пытаться получить имя urlpattern в представлении. Параметры urlpattern практически не зависят от параметров представления, на которое они указывают. Если вы хотите указать на определенный URL-адрес, вам необходимо знать, как работает шаблон URL-адреса, а не только как работает представление. Если вам нужно знать, как работает urlpattern, вам также может потребоваться знать имя urlpattern.

Конли Оуэнс
источник
3

Просто попробуй request.path. Это получит текущий запрашиваемый путь.

Абхишек Айенгар
источник
1

Это немного неясно из вашего вопроса, но http://docs.djangoproject.com/en/dev/topics/http/urls/ , вероятно, даст объяснение тому, что вам нужно.

Особенно полезно отметить, как Django обрабатывает запросы:

Когда пользователь запрашивает страницу с вашего сайта на Django, система следует этому алгоритму, чтобы определить, какой код Python выполнить:

  1. Django определяет используемый корневой модуль URLconf. Обычно это значение параметра ROOT_URLCONF, но если входящий объект HttpRequest имеет атрибут urlconf (установленный обработкой запроса промежуточного программного обеспечения), его значение будет использоваться вместо параметра ROOT_URLCONF.
  2. Django загружает этот модуль Python и ищет переменные urlpatterns. Это должен быть список Python в формате, возвращаемом функцией django.conf.urls.defaults.patterns ().
  3. Django проходит по каждому шаблону URL по порядку и останавливается на первом, который соответствует запрошенному URL.
  4. Как только одно из регулярных выражений совпадает, Django импортирует и вызывает заданное представление, которое является простой функцией Python. Представлению передается HttpRequest в качестве первого аргумента и любые значения, захваченные в регулярном выражении, в качестве оставшихся аргументов.

Если вы сразу после полного пути, вы можете попробовать:

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

Я надеюсь, что это поможет - оно показывает, как использовать модуль URLconf, и, надеюсь, поможет указать вам правильное направление.

Марк Мэйо
источник
Спасибо, но я это знаю :-) Я добавил несколько пояснений, чтобы избежать недоразумений.
e-satis