Шаблон 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-функции для фильтрации.
Начинающий в Питоне. Все никак не мог понять зачем name и namespace. Тут коротко и ясно. Спасибо.
Все отлично написано. Автор молодец.