Диспетчер URL
Чистая и элегантная схема URL — важный аспект качественного веб-приложения. Django позволяет проектировать URL так, как вам нужно, без ограничений, накладываемых фреймворком.
См. 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. Она должна быть последовательностью объектовdjango.urls.path()и/илиdjango.urls.re_path(). - Django последовательно перебирает все шаблоны URL и останавливается на первом, который соответствует запрошенному URL, сопоставляя его с
path_info. - После того, как один из шаблонов 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— Соответствует любой строке-тэгу, состоящей из букв или цифр 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, если он не может преобразовать данное значение.ValueErrorинтерпретируется как отсутствие соответствия, и в результате пользователю отправляется ответ 404, если другой шаблон URL не соответствует. - Метод
to_url(self, value), который обрабатывает преобразование типа Python в строку, используемую в URL. Он должен генерировать исключениеValueError, если он не может преобразовать данное значение.ValueErrorинтерпретируется как отсутствие соответствия, и в результатеreverse()сгенерируетNoReverseMatch, если другой шаблон 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-([0-9]+)/)?$', blog_articles), # bad
re_path(r'^comments/(?:page-(?P<page_number>[0-9]+)/)?$', 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 должна быть последовательностью экземпляров 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 (трудоёмкий, не масштабируемый и подверженный ошибкам подход). Также опасно разрабатывать специальные механизмы для генерации 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.
END_OF_DOCUMENT_MARKERВ некоторых сценариях, где представления имеют общий характер, между 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() сопоставляет количество аргументов и имена ключевых аргументов. Конвертеры путей также могут вызывать ValueError для указания отсутствия совпадения, см. Регистрация пользовательских конвертеров путей для получения подробностей.
Пространства имён 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'. Предположим, мы улучшили это приложение таким образом, чтобы оно учитывало имя пространства имён экземпляра при создании и отображении опросов.
urls.pyfrom django.urls import include, path
urlpatterns = [
path('author-polls/', include('polls.urls', namespace='author-polls')),
path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]
polls/urls.pyfrom 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. Это будет'publisher-polls'. -
'author-polls:index'всегда будет преобразовано в главную страницу экземпляра'author-polls'(и аналогично для'publisher-polls') .
Если также был бы экземпляр по умолчанию — например, экземпляр с именем 'polls' — единственное изменение по сравнению с вышеизложенным было бы в случае, когда нет текущего экземпляра (второй пункт в списке выше). В этом случае 'polls:index' будет преобразовано в главную страницу экземпляра по умолчанию, а не экземпляра, объявленного последним в urlpatterns.
Пространства имён URL и подключаемые URLconf
Пространства имён приложения подключаемых URLconf можно указать двумя способами.
Во-первых, вы можете установить атрибут app_name в модуле подключенного URLconf, на одном уровне с атрибутом urlpatterns . Вы должны передать фактический модуль или строку, ссылающуюся на модуль, в include(), а не сам список urlpatterns.
polls/urls.pyfrom 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'),
...
]
urls.pyfrom django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
]
Указанные в polls.urls URL-адреса будут иметь пространство имен приложения 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/4.1/topics/http/urls/