Диспечер 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(установленный средством обработки), его значение будет использовано вместо значения настройки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),
...,
]
Устарело начиная с версии 5.1: Переопределение существующих преобразователей с помощью django.urls.register_converter() устарело.
Использование регулярных выражений
Если синтаксис путей и преобразователей недостаточно для определения ваших шаблонов 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, которое было захвачено.
Производительность
Django обрабатывает регулярные выражения в списке urlpatterns, который компилируется при первом обращении. Последующие запросы используют кэшированную конфигурацию через резолвер URL.
Синтаксис переменной 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 — идентификатор (например, имя) представления, отвечающего за его обработку. Другие необходимые данные для поиска нужного 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>/.
Вы можете получить эти URL в коде шаблона, используя:
<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() соответствует количеству аргументов и именам ключевых аргументов. Конвертеры путей также могут вызывать 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. Это будет'publisher-polls', так как он объявлен последним вurlpatterns. -
'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")),
]
У URL-адресов, определённых в polls.urls, будет пространство имён приложения polls.
Во-вторых, вы можете включить объект, содержащий вложенные данные пространства имён. Если вы include() список объектов path() или re_path(), URL-адреса, содержащиеся в этом объекте, будут добавлены в глобальное пространство имён. Однако вы также можете include() пару из двух элементов, содержащую:
(<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-шаблоны в указанное пространство имён приложения.
END_OF_DOCUMENT_MARKERПространство имен экземпляра можно указать, используя аргумент namespace для include(). Если пространство имен экземпляра не указано, оно будет по умолчанию совпадать с пространством имён приложения включённого URLconf. Это означает, что оно также будет экземпляром по умолчанию для этого пространства имён.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.1/topics/http/urls/