Диспетчер URL
Чистая и элегантная схема URL — важная деталь высококачественного веб-приложения. Django позволяет проектировать URL как вам угодно, без ограничений фреймворка.
Не требуется .php или .cgi, и уж тем более никакого 0,2097,1-1-1928,00 вздора.
См. Cool URIs don’t change, авторство Тимоти Бернерс-Ли, создателя Всемирной паутины, для отличных аргументов в пользу того, почему URL должны быть чистыми и удобными для использования.
Обзор
Для проектирования URL для приложения вы создаёте модуль Python, неофициально называемый URLconf (URL-конфигурация). Этот модуль — это чистый код Python, и он представляет собой отображение между выражениями пути URL и функциями Python (вашими представлениями).
Это отображение может быть коротким или длинным, сколько потребуется. Оно может ссылаться на другие отображения. И, поскольку это чистый код Python, он может быть построен динамически.
Django также предоставляет способ перевода URL в соответствии с активным языком. Для получения дополнительной информации см. документацию по международной локализации.
Как Django обрабатывает запрос
Когда пользователь запрашивает страницу на вашем сайте, работающем на Django, система использует следующий алгоритм, чтобы определить, какой код Python выполнить:
- Django определяет модуль корневого URLconf, который нужно использовать. Обычно это значение параметра
ROOT_URLCONF, но если объект входящегоHttpRequestимеет атрибутurlconf(установленный middleware), его значение будет использоваться вместо параметраROOT_URLCONF. - Django загружает этот модуль Python и ищет переменную
urlpatterns. Она должна быть списком Python из экземпляровdjango.urls.path()и/илиdjango.urls.re_path(). - Django проходит по каждой паттерну URL в порядке и останавливается на первом, который соответствует запрошенному URL.
- После того, как один из паттернов URL совпадёт, Django импортирует и вызывает заданное представление, которое является простой функцией Python (или представление на основе класса). Представление получает следующие аргументы:
- Экземпляр
HttpRequest. - Если сопоставленный паттерн URL не возвратил именованные группы, то совпадения из регулярного выражения передаются как позиционные аргументы.
- Именованные аргументы состоят из любых именованных частей, соответствующих выражению пути, перезаписанные любыми аргументами, указанными в необязательном аргументе
kwargsкdjango.urls.path()илиdjango.urls.re_path().
- Экземпляр
- Если ни один паттерн URL не соответствует, или если во время любого этапа этого процесса возникает исключение, Django вызывает соответствующее представление для обработки ошибок. См. Обработка ошибок ниже.
Пример
Вот пример URLconf:
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
Примечания:
- Для захвата значения из URL используйте угловые скобки.
- Захваченные значения могут необязательно включать тип преобразователя. Например, используйте
<int:name>для захвата целочисленного параметра. Если преобразователь не указан, соответствует любая строка, за исключением символа/. - Нет необходимости добавлять ведущую косую черту, поскольку у каждого URL она есть. Например, это
articles, а не/articles.
Примеры запросов:
- Запрос на
/articles/2005/03/будет соответствовать третьему элементу в списке. Django вызовет функциюviews.month_archive(request, year=2005, month=3). -
/articles/2003/будет соответствовать первому паттерну в списке, а не второму, так как паттерны проверяются в порядке, и первый — это первое успешно пройденное. Не стесняйтесь использовать порядок для вставки специальных случаев, как в этом случае. Django вызовет функциюviews.special_case_2003(request) -
/articles/2003не будет соответствовать ни одному из этих паттернов, поскольку каждый паттерн требует, чтобы URL заканчивался косой чертой. -
/articles/2003/03/building-a-django-site/будет соответствовать последнему паттерну. Django вызовет функциюviews.article_detail(request, year=2003, month=3, slug="building-a-django-site").
Преобразователи путей
По умолчанию доступны следующие преобразователи путей:
-
str— Соответствует любой непустой строке, исключая разделитель пути,'/'. Это значение по умолчанию, если преобразователь не указан в выражении. -
int— Соответствует нулю или любому положительному целому числу. Возвращаетint. -
slug— Соответствует любой строке slug, состоящей из ASCII-букв или цифр, а также символов дефиса и нижнего подчеркивания. Например,building-your-1st-django-site. -
uuid— Соответствует отформатированному UUID. Чтобы избежать множественных URL, отображающихся на одну и ту же страницу, дефисы должны быть включены, а буквы — строчными. Например,075194d3-6885-417e-a8a8-6c931e272f00. Возвращает экземплярUUID. -
path— Соответствует любой непустой строке, включая разделитель пути,'/'. Это позволяет сопоставлять весь путь URL, а не только часть пути URL, как вstr.
Регистрация пользовательских преобразователей путей
Для более сложных требований к сопоставлению вы можете определить собственные преобразователи путей.
Преобразователь — это класс, который включает следующее:
- Атрибут класса
regex, как строка. - Метод
to_python(self, value), который обрабатывает преобразование сопоставленной строки в тип, который должен быть передан функции представления. Он должен вызватьValueErrorесли не может преобразовать данное значение. - Метод
to_url(self, value), который обрабатывает преобразование типа Python в строку, которая будет использоваться в URL.
Например:
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
Зарегистрируйте пользовательские классы преобразователей в своём URLconf, используя register_converter():
from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]
Использование регулярных выражений
Если синтаксис путей и преобразователей недостаточно для определения ваших паттернов URL, вы также можете использовать регулярные выражения. Для этого используйте re_path() вместо path().
В Python синтаксис именованных групп регулярных выражений — (?P<name>pattern), где name — имя группы, а pattern — некоторый шаблон для сопоставления.
Вот пример URLconf из предыдущего примера, переписанный с использованием регулярных выражений:
from django.urls import path, re_path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]
Это выполняет примерно то же самое, что и предыдущий пример, за исключением:
- Сопоставление точных URL несколько ограничено. Например, год 10000 больше не будет соответствовать, так как целые числа года ограничены ровно четырьмя цифрами.
- Каждый захваченный аргумент передаётся представлению как строка, независимо от того, какое сопоставление выполняет регулярное выражение.
При переходе от использования path() к re_path() или наоборот, важно понимать, что тип аргументов представления может измениться, и вам, возможно, придётся адаптировать ваши представления.
Использование безымянных групп регулярных выражений
Помимо именованного синтаксиса группировки, например (?P<year>[0-9]{4}), можно также использовать более короткий безымянный, например ([0-9]{4}).
Это использование не особенно рекомендуется, так как оно облегчает случайное введение ошибок между предполагаемым значением совпадения и аргументами представления.
В любом случае, рекомендуется использовать только один стиль в данном регулярном выражении. Если оба стиля смешаны, все безымянные группы игнорируются, и только именованные группы передаются функции представления.
Вложенные аргументы
Регулярные выражения позволяют вложенные аргументы, и Django будет их разрешать и передавать представлению. При обратном преобразовании Django будет пытаться заполнить все внешние захваченные аргументы, игнорируя любые вложенные захваченные аргументы. Рассмотрим следующие шаблоны URL, которые необязательно принимают аргумент страницы:
from django.urls import re_path
urlpatterns = [
re_path(r'^blog/(page-(\d+)/)?$', blog_articles), # bad
re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), # good
]
Оба паттерна используют вложенные аргументы и будут разрешены: например, blog/page-2/ приведет к совпадению с blog_articles с двумя позиционными аргументами: page-2/ и 2. Второй паттерн для comments будет соответствовать comments/page-2/ с именованным аргументом page_number, установленным в 2. Внешний аргумент в этом случае — незахватывающий аргумент (?:...).
Представление blog_articles нуждается во внешнем захваченном аргументе для обратного преобразования, page-2/ или в отсутствии аргументов в данном случае, в то время как comments может быть обращено с любыми аргументами или значением для page_number.
Вложенные захваченные аргументы создают сильную связь между аргументами представления и URL, как показано в blog_articles: представление получает часть URL (page-2/) вместо только значения, которое интересует представление. Эта связь ещё сильнее проявляется при обратном преобразовании, так как для обратного преобразования представления нам нужно передать часть URL, а не только номер страницы.
Как правило, захватывайте только те значения, с которыми представлению нужно работать, и используйте незахватывающие аргументы, когда регулярное выражение требует аргумента, но представление его игнорирует.
Что ищет URLconf
URLconf ищет по запрошенному URL как обычной строке Python. Это не включает параметры GET или POST, или доменное имя.
Например, в запросе на https://www.example.com/myapp/, URLconf будет искать myapp/.
В запросе на https://www.example.com/myapp/?page=3, URLconf будет искать myapp/.
URLconf не рассматривает метод запроса. Другими словами, все методы запроса — POST, GET, HEAD, и т. д. — будут маршрутизированы к той же функции для одного и того же URL.
Указание значений по умолчанию для аргументов представления
Удобный способ — указать значения по умолчанию для аргументов ваших представлений. Вот пример URLconf и представления:
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page),
]
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...
В приведённом примере оба URL-шаблона указывают на одно и то же представление — views.page — но первый шаблон ничего не извлекает из URL. Если совпадёт первый шаблон, функция page() будет использовать значение по умолчанию для аргумента num, 1. Если совпадёт второй шаблон, page() будет использовать значение, извлечённое для num.
Производительность
Каждый регулярное выражение в urlpatterns компилируется при первом обращении. Это делает систему невероятно быстрой.
Синтаксис переменной urlpatterns
urlpatterns должна быть списком Python из экземпляров path() и/или re_path().
Обработка ошибок
Если Django не может найти совпадение для запрошенного URL или возникает исключение, Django вызывает представление для обработки ошибок.
Представления для этих случаев задаются четырьмя переменными. Их значения по умолчанию подходят для большинства проектов, но дополнительная настройка возможна путём переопределения значений по умолчанию.
Полные подробности см. в документации по настройке представлений обработки ошибок.
Эти значения можно задать в вашем корневом URLconf. Настройка этих переменных в любом другом URLconf не подействует.
Значения должны быть вызываемыми объектами или строками, представляющими полный путь импорта Python к представлению, которое должно вызываться для обработки соответствующей ситуации с ошибкой.
Переменные:
-
handler400— см.django.conf.urls.handler400. -
handler403— см.django.conf.urls.handler403. -
handler404— см.django.conf.urls.handler404. -
handler500— см.django.conf.urls.handler500.
Включение других URLconf
В любой момент ваш urlpatterns может «включать» другие модули URLconf. Это по сути «устанавливает корень» набора URL под другими.
Например, вот выдержка из URLconf для самого сайта Django. Он включает несколько других URLconf:
from django.urls import include, path
urlpatterns = [
# ... snip ...
path('community/', include('aggregator.urls')),
path('contact/', include('contact.urls')),
# ... snip ...
]
Когда Django сталкивается с include(), он отбрасывает ту часть URL, которая совпала до этого момента, и отправляет оставшуюся строку включённому URLconf для дальнейшей обработки.
Ещё один вариант — включение дополнительных URL-шаблонов с помощью списка экземпляров path(). Например, рассмотрим этот URLconf:
from django.urls import include, path
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
path('reports/', credit_views.report),
path('reports/<int:id>/', credit_views.report),
path('charge/', credit_views.charge),
]
urlpatterns = [
path('', main_views.homepage),
path('help/', include('apps.help.urls')),
path('credit/', include(extra_patterns)),
]
В этом примере URL /credit/reports/ будет обрабатываться представлением Django credit_views.report().
Это можно использовать для удаления избыточности из URLconf, где один префикс пути используется многократно. Например, рассмотрим этот URLconf:
from django.urls import path
from . import views
urlpatterns = [
path('<page_slug>-<page_id>/history/', views.history),
path('<page_slug>-<page_id>/edit/', views.edit),
path('<page_slug>-<page_id>/discuss/', views.discuss),
path('<page_slug>-<page_id>/permissions/', views.permissions),
]
Мы можем улучшить его, указав общий префикс пути только один раз и сгруппировав разные суффиксы:
from django.urls import include, path
from . import views
urlpatterns = [
path('<page_slug>-<page_id>/', include([
path('history/', views.history),
path('edit/', views.edit),
path('discuss/', views.discuss),
path('permissions/', views.permissions),
])),
]
Переменные, полученные из соответствия
Включённый URLconf получает любые переменные, полученные от родительских URLconf, поэтому следующий пример допустим:
# In settings/urls/main.py
from django.urls import include, path
urlpatterns = [
path('<username>/blog/', include('foo.urls.blog')),
]
# In foo/urls/blog.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.blog.index),
path('archive/', views.blog.archive),
]
В приведённом примере переменная "username" передаётся включённому URLconf, как ожидалось.
Передача дополнительных параметров функциям представления
URLconf имеет точку подключения, позволяющую передавать дополнительные аргументы вашим функциям представления в виде словаря Python.
Функция path() может принимать необязательный третий аргумент, который должен быть словарем дополнительных ключевых аргументов для передачи функции представления.
Например:
from django.urls import path
from . import views
urlpatterns = [
path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]
В этом примере для запроса к /blog/2005/, Django вызовет views.year_archive(request, year=2005, foo='bar').
Этот метод используется в фреймворке аггрегации для передачи метаданных и параметров представлениям.
Обработка конфликтов
Возможно наличие URL-шаблона, который получает именованные ключевые аргументы, а также передаёт аргументы с теми же именами в словаре дополнительных аргументов. В этом случае аргументы в словаре будут использоваться вместо аргументов, извлечённых из URL.
Передача дополнительных параметров в include()
Аналогично, вы можете передавать дополнительные параметры include(), и каждая строка в включённом URLconf получит эти дополнительные параметры.
Например, эти два набора URLconf функционально идентичны:
Первый набор:
# main.py
from django.urls import include, path
urlpatterns = [
path('blog/', include('inner'), {'blog_id': 3}),
]
# inner.py
from django.urls import path
from mysite import views
urlpatterns = [
path('archive/', views.archive),
path('about/', views.about),
]
Второй набор:
# main.py
from django.urls import include, path
from mysite import views
urlpatterns = [
path('blog/', include('inner')),
]
# inner.py
from django.urls import path
urlpatterns = [
path('archive/', views.archive, {'blog_id': 3}),
path('about/', views.about, {'blog_id': 3}),
]
Обратите внимание, что дополнительные параметры всегда передаются каждой строке включённого URLconf, независимо от того, принимает ли представление этой строки эти параметры в качестве допустимых. По этой причине этот метод полезен только если вы уверены, что каждое представление во включённом URLconf принимает передаваемые дополнительные параметры.
Обратная адресация URL
Частая необходимость при работе с проектом Django — возможность получить URL в окончательном виде, либо для вставки в генерируемое содержимое (URL представлений и ресурсов, отображаемые пользователю и т. п.), либо для обработки потока навигации на стороне сервера (перенаправления и т. п.).
Крайне нежелательно жёстко кодировать эти URL (трудоёмкий, не масштабируемый и подверженный ошибкам подход). Также опасно разрабатывать самодельные механизмы генерации URL, аналогичные описанному в URLconf, что может привести к созданию устаревших URL со временем.
Другими словами, нужен DRY-механизм. Среди прочих преимуществ он позволит модифицировать структуру URL без необходимости прохода по всему исходному коду проекта для поиска и замены устаревших URL.
Основная информация для получения URL — идентификатор (например, имя) представления, ответственного за его обработку. Другая необходимая информация — типы (позиционные, ключевые) и значения аргументов представления.
Django предоставляет решение, в котором маппер URL является единственным хранилищем структуры URL. Вы передаёте ему свой URLconf, и затем он может использоваться в обоих направлениях:
- Начиная с запрошенного пользователем/браузером URL, он вызывает соответствующее представление Django, предоставляя необходимые аргументы с их значениями, извлечёнными из URL.
- Начиная с идентификатора соответствующего представления Django плюс значений аргументов, которые будут переданы ему, получить связанный URL.
Первый случай — использование, о котором мы говорили в предыдущих разделах. Второй — то, что известно как обратная адресация URL, обратное соответствие URL, обратный поиск URL или просто обратная адресация URL.
Django предоставляет инструменты для выполнения обратной адресации URL, соответствующие различным уровням, где требуются URL:
- В шаблонах: используя тег шаблона
url. - В коде Python: используя функцию
reverse(). - В коде более высокого уровня, связанном с обработкой URL экземпляров модели Django: метод
get_absolute_url().
Примеры
Рассмотрим снова эту запись URLconf:
from django.urls import path
from . import views
urlpatterns = [
#...
path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
#...
]
Согласно этому дизайну, URL для архива, соответствующего году nnnn, это /articles/<nnnn>/.
Вы можете получить его в коде шаблона, используя:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
Или в коде Python:
from django.http import HttpResponseRedirect
from django.urls import reverse
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
Если по какой-то причине было решено изменить URL, по которым публикуются архивы статей на год, то вам нужно будет изменить только запись в URLconf.
В некоторых сценариях, где представления имеют общий характер, между URL и представлениями может быть многозначное отношение. В таких случаях имя представления не является достаточным идентификатором для обратной адресации URL. Прочитайте следующий раздел, чтобы узнать о решении, которое предоставляет Django для этого.
Именование URL-шаблонов
Для выполнения обратной адресации URL вам необходимо использовать именованные URL-шаблоны, как в приведённых выше примерах. Строка, используемая для имени URL, может содержать любые символы. Вы не ограничены именами, допустимыми в Python.
При именовании URL-шаблонов выбирайте имена, которые, скорее всего, не совпадут с именами, выбранными другими приложениями. Если вы назовёте свой URL-шаблон comment и другое приложение сделает то же самое, URL, который reverse() найдёт, зависит от того, какой шаблон находится последним в списке urlpatterns вашего проекта.
Добавление префикса к именам URL, возможно, из имени приложения (например, myapp-comment вместо comment), уменьшает вероятность коллизии.
Вы можете намеренно выбрать то же самое имя URL, что и у другого приложения, если хотите переопределить представление. Например, распространённым случаем использования является переопределение представления LoginView. Части Django и большинство приложений сторонних разработчиков предполагают, что это представление имеет шаблон URL с именем login. Если у вас есть пользовательское представление входа и вы присвоите его URL имя login, reverse() найдёт ваше пользовательское представление, пока оно находится в urlpatterns после того, как django.contrib.auth.urls включён (если это вообще включено).
Вы также можете использовать одно имя для нескольких шаблонов URL, если они отличаются своими аргументами. В дополнение к имени URL, reverse() соответствует количеству аргументов и именам ключевых аргументов.
Пространства имён URL
Введение
Пространства имён URL позволяют вам однозначно обращаться к именованным шаблонам URL, даже если разные приложения используют одни и те же имена URL. Это хорошая практика для приложений сторонних разработчиков — всегда использовать именованные URL (как мы делали в учебнике). Аналогично, это также позволяет вам обращаться к URL, если несколько экземпляров приложения развернуты. Другими словами, так как несколько экземпляров одного приложения будут совместно использовать именованные URL, пространства имён предоставляют способ отличить эти именованные URL друг от друга.
Приложения Django, которые должным образом используют пространства имён URL, могут быть развернуты более одного раза для конкретного сайта. Например, django.contrib.admin имеет класс AdminSite, который позволяет вам легко развернуть более одного экземпляра админ-панели. В последующем примере мы обсудим идею развертывания приложения опросов из учебника в двух разных местах, чтобы мы могли предоставить одинаковую функциональность двум разным аудиториям (авторам и издателям).
Пространство имён URL состоит из двух частей, обе из которых являются строками:
-
application namespace - Это описывает имя приложения, которое развертывается. Каждый экземпляр одного приложения будет иметь то же самое пространство имён приложения. Например, приложение администрирования Django имеет достаточно предсказуемое пространство имён приложения
'admin'. -
instance namespace - Это идентифицирует конкретный экземпляр приложения. Пространства имён экземпляров должны быть уникальными во всем вашем проекте. Однако пространство имён экземпляра может быть таким же, как и пространство имён приложения. Это используется для указания по умолчанию экземпляра приложения. Например, у экземпляра администрирования Django по умолчанию пространство имён экземпляра
'admin'.
Именованные URL задаются с использованием оператора ':'. Например, главная страница индекса приложения администрирования ссылается на 'admin:index'. Это указывает на пространство имён 'admin', и именованный URL 'index'.
Пространства имён также могут быть вложенными. Имя URL 'sports:polls:index' будет искать шаблон с именем 'index' в пространстве имён 'polls', которое само по себе определено внутри пространства имён верхнего уровня 'sports'.
Обращение к именованным URL в пространствах имён
При задании именованного URL (например, 'polls:index') для разрешения, Django разделяет полное имя на части и затем выполняет следующий поиск:
- Сначала Django ищет соответствующее пространство имён приложения (в этом примере
'polls'). Это даст список экземпляров этого приложения. -
Если определено текущее приложение, Django находит и возвращает решатель URL для этого экземпляра. Текущее приложение может быть указано с помощью аргумента
current_appк функцииreverse().Тег шаблона
urlиспользует пространство имён текущего разрешённого представления в качестве текущего приложения вRequestContext. Вы можете переопределить этот параметр по умолчанию, установив текущее приложение в атрибутеrequest.current_app. - Если текущего приложения нет. Django ищет экземпляр приложения по умолчанию. Экземпляр приложения по умолчанию — это экземпляр, у которого пространство имён экземпляра соответствует пространству имён приложения (в этом примере экземпляр
pollsс именем'polls'). - Если экземпляра приложения по умолчанию нет, Django выберет последний развернутый экземпляр приложения, какое бы имя экземпляра оно ни имело.
- Если указанное пространство имён не соответствует пространству имён приложения на шаге 1, Django попытается выполнить прямой поиск пространства имён в качестве пространства имён экземпляра.
Если пространства имён вложены, эти шаги повторяются для каждой части пространства имён, пока не останется только имя представления. Затем имя представления будет разрешено в URL в найденном пространстве имён.
Пример
Чтобы продемонстрировать стратегию разрешения на практике, рассмотрим пример двух экземпляров приложения polls из учебника: один называется 'author-polls', а другой 'publisher-polls'. Предположим, мы улучшили это приложение, чтобы оно учитывало пространство имён экземпляра при создании и отображении опросов.
from django.urls import include, path
urlpatterns = [
path('author-polls/', include('polls.urls', namespace='author-polls')),
path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
...
]
Используя эту настройку, возможны следующие поиски:
-
Если один из экземпляров является текущим — скажем, если мы отображали страницу деталей в экземпляре
'author-polls'—'polls:index'будет разрешено в главную страницу экземпляра'author-polls'; т.е. оба следующих результата дадут"/author-polls/".В методе представления на основе класса:
reverse('polls:index', current_app=self.request.resolver_match.namespace)и в шаблоне:
{% url 'polls:index' %} - Если текущего экземпляра нет — скажем, если мы отображали страницу где-то ещё на сайте —
'polls:index'будет разрешено в последний зарегистрированный экземплярpolls. Поскольку нет экземпляра по умолчанию (пространство имён экземпляра'polls'), будет использован последний зарегистрированный экземплярpolls, который зарегистрирован последним вurlpatterns. -
'author-polls:index'всегда будет разрешено в главную страницу экземпляра'author-polls'(и аналогично для'publisher-polls') .
Если также был экземпляр по умолчанию — скажем, экземпляр с именем 'polls' — единственное изменение по сравнению с вышеизложенным будет в случае, когда нет текущего экземпляра (второй пункт в списке выше). В этом случае 'polls:index' будет разрешено в главную страницу экземпляра по умолчанию, а не в экземпляр, объявленный последним в urlpatterns.
Пространства имён URL и включённые URLconf
Пространства имён приложения включённых URLconf можно указать двумя способами.
Во-первых, вы можете установить атрибут app_name в модуле включённого URLconf, на том же уровне, что и атрибут urlpatterns . Вы должны передать фактический модуль или строковое имя ссылки на модуль в include(), а не сам список urlpatterns.
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
...
]
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
]
URL, определённые в polls.urls будут иметь пространство имён приложения polls.
Во-вторых, вы можете включить объект, содержащий данные вложенного пространства имён. Если вы include() список экземпляров path() или re_path(), URL, содержащиеся в этом объекте, будут добавлены в глобальное пространство имён. Однако вы также можете include() 2-кортеж, содержащий:
(<list of path()/re_path() instances>, <application namespace>)
Например:
from django.urls import include, path
from . import views
polls_patterns = ([
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
], 'polls')
urlpatterns = [
path('polls/', include(polls_patterns)),
]
Это включит указанные шаблоны URL в заданное пространство имён приложения.
Пространство имён экземпляра можно указать с помощью аргумента namespace к include(). Если пространство имён экземпляра не указано, оно будет по умолчанию равно пространству имён приложения включённого URLconf. Это также будет экземпляром по умолчанию для этого пространства имён.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.0/topics/http/urls/