Ссылки, namespaсe и name в шаблонах Django

Шаблон Django — это обычный HTML, в который включены теги шаблонизатора. В шаблонах будет работать любой HTML-код, в том числе и ссылки:

<a class="navbar-brand" href="ice_cream/">
  Страница со списком сортов мороженого
</a> 

Но если расставить ссылки в шаблонах именно таким образом, то очень скоро код станет неуправляемым: если потребуется поменять пути в urls.py, придётся менять все ссылки в шаблонах. Это неудобно и нарушает принцип DRY.Для решения этой задачи придумали использовать имена name для каждого path() в списке urlpatterns. И если вместо конкретной ссылки в шаблоне указать name, шаблонизатор обратится к нужному path(), возьмёт адрес ссылки прямо из него и при рендеринге вставит этот адрес в HTML.

Имя name в ссылках

Установим для path() параметр name:

# anfisa/ice_cream/urls.py

urlpatterns = [
    path('ice_cream/', views.ice_cream_list, name='ice_cream_list'),
] 

Теперь вместо конкретного адреса в шаблонах можно использовать имя ice_cream_list, указывая его в тегах адресов {% url %}:

{% comment %}
В HTML-тег <a> в атрибут href вместо адреса ссылки вставляем тег {% url %}
и указываем name нужного path() 
{% endcomment %}
<a class="navbar-brand" href="{% url 'ice_cream_list' %}">
  Страница со списком сортов мороженого
</a> 

При рендеринге в шаблоне будет создана ссылка из path() c name='ice_cream_list':

<a class="navbar-brand" href="ice_cream/">
  Страница со списком сортов мороженого
</a> 

Если по каким-то причинам в path() придётся изменить адрес на другой…

# anfisa/ice_cream/urls.py

urlpatterns = [
    path('new_ice_cream/', views.ice_cream_list, name='ice_cream_list'),
] 

…то в шаблонах ничего менять не придётся: адрес автоматически подтянется из нужного path(), и при рендеринге на странице будет новая ссылка:

<a class="navbar-brand" href="new_ice_cream/">
  Страница со списком сортов мороженого
</a> 

Чудо чудное: всё работает! Узнать ещё больше о name можно из документации.

Пространство имён namespace

При подключении новых приложений к Django-проекту их urls.py через инструкцию include включаются в головной urls.py проекта. Но если в разных приложениях будут path() с одинаковыми name, то возникнет проблема: при обращении по такому «дублирующемуся» name всегда будет вызываться path() из того urls.py, который в головном urlpatterns подключён ближе к началу списка.Избегать таких коллизий помогает параметр namespace (англ. «пространство имён»). Его передают третьим параметром при подключении urls.py приложения через include. Обычно для namespace указывают имя, совпадающее с названием приложения.Вот как это выглядит в коде:

# anfisa/urls.py
urlpatterns = [
   # Добавляем к путям из приложения ice_cream пространство имён ice_cream
    path('', include('ice_cream.urls', namespace='ice_cream')),
] 

В urls.py подключаемого приложения должна быть объявлена переменная app_name, в которой тоже указывается namespace для путей приложения:

# anfisa/ice_cream/urls.py
# Эта строчка обязательна. 
# Без неё namespace работать не будет:
# namespace должен быть объявлен при include и тут, в app_name
app_name = 'ice_cream'

urlpatterns = [
    path('ice_cream/', views.ice_cream_list, name='ice_cream_list'),
] 

Tеперь в шаблоне можно обратиться к ссылке так:

<a class="navbar-brand" href="{% url 'ice_cream:ice_cream_list' %}">
  Анфиса для друзей
</a> 

На человеческий язык этот код можно перевести так: «из пространства имён namespace='ice_cream' получить адрес из path() с name='ice_cream_list'». Больше конфликтов не будет: namespace уверенно укажет, к какому именно path() нужно обратиться, даже если name приложений дублируются.О namespace есть смысл почитать и в официальной документации, там тоже интересно.

Переменные в путях

Разумеется, можно формировать и ссылки с переменными в путях. Например, в проекте «Анфиса для друзей» ссылка на подробную информацию о мороженом сделана вот так:

<a href="{% url 'ice_cream:ice_cream_detail' ice_cream.pk %}">
  Подробная информация
</a> 
  • ice_cream — пространство имён, namespace.
  • ice_cream_detail — name из path().
  • ice_cream.pk — переданный параметр. В примере это pk (primary key) запрошенного мороженного. Будет использоваться во view-функции для фильтрации.




Комментарии: 1
  1. Евгений

    Начинающий в Питоне. Все никак не мог понять зачем name и namespace. Тут коротко и ясно. Спасибо.

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: