Диспечер 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(установленный средством), его значение будет использоваться вместо значения параметраROOT_URLCONF. - Django загружает этот модуль Python и ищет переменную
urlpatterns. Это должен быть список Python экземпляровdjango.conf.urls.url(). - Django проходит по каждому шаблону URL в порядке и останавливается на первом шаблоне, который соответствует запрошенному URL.
- После того, как одно из регулярных выражений совпадёт, Django импортирует и вызывает заданное представление, которое является простой функцией Python (или представлением на основе класса представление на основе класса). Представление получает следующие аргументы:
- Экземпляр
HttpRequest. - Если совпавшее регулярное выражение не возвратило именованные группы, то совпадения из регулярного выражения предоставляются как позиционные аргументы.
- Именованные аргументы составляют любые именованные группы, соответствующие регулярному выражению, переопределяемые любыми аргументами, указанными в необязательном аргументе
kwargsкdjango.conf.urls.url().
- Экземпляр
- Если ни одно регулярное выражение не совпадёт или во время этого процесса будет возбуждено исключение, Django вызовет соответствующее представление для обработки ошибок. См. Обработка ошибок ниже.
Пример
Вот пример URLconf:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
Примечания:
- Чтобы захватить значение из URL, просто поместите скобки вокруг него.
- Не нужно добавлять ведущий слеш, потому что у каждого URL есть это. Например, это
^articles, а не^/articles. - Префикс
'r'перед каждой строкой регулярного выражения необязателен, но рекомендуется. Он сообщает Python, что строка является «сырой» — что ничего в строке не должно быть экранировано. См. Dive Into Python’s explanation.
Примеры запросов:
- Запрос на
/articles/2005/03/будет соответствовать третьей записи в списке. Django вызовет функциюviews.month_archive(request, '2005', '03'). -
/articles/2005/3/не будет соответствовать никаким шаблонам URL, потому что третья запись в списке требует двух цифр для месяца. -
/articles/2003/будет соответствовать первому шаблону в списке, а не второму, потому что шаблоны проверяются в порядке, и первый шаблон — первая проверка, которая проходит. Не стесняйтесь использовать порядок, чтобы вставить особые случаи, такие как этот. Здесь Django вызовет функциюviews.special_case_2003(request) -
/articles/2003не будет соответствовать ни одному из этих шаблонов, потому что каждый шаблон требует, чтобы URL заканчивался слешем. -
/articles/2003/03/03/будет соответствовать последнему шаблону. Django вызовет функциюviews.article_detail(request, '2003', '03', '03').
Именованные группы
В приведенном выше примере использовались простые, *не именованные* группы регулярных выражений (в скобках) для захвата фрагментов URL и передачи их в виде *позиционных* аргументов представлению. В более продвинутом использовании можно использовать *именованные* группы регулярных выражений для захвата фрагментов URL и передачи их в виде *именованных* аргументов представлению.
В Python регулярных выражениях синтаксис именованных групп регулярных выражений — (?P<name>pattern), где name — имя группы, а pattern — некоторый шаблон для сопоставления.
Вот приведенный выше пример URLconf, переписанный с использованием именованных групп:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
Это достигает точно того же, что и предыдущий пример, с одним небольшим отличием: захваченные значения передаются функциям представлений в качестве именованных аргументов, а не позиционных. Например:
- Запрос на
/articles/2005/03/вызовет функциюviews.month_archive(request, year='2005', month='03'), а неviews.month_archive(request, '2005', '03'). - Запрос на
/articles/2003/03/03/вызовет функциюviews.article_detail(request, year='2003', month='03', day='03').
На практике это означает, что ваши URLconf немного более явные и менее подвержены ошибкам порядка аргументов — и вы можете изменить порядок аргументов в определениях функций представлений. Конечно, эти преимущества идут ценой краткости; некоторые разработчики считают синтаксис с именованными группами некрасивым и слишком громоздким.
Алгоритм сопоставления/группирования
Вот алгоритм, которому следует анализатор URLconf, с точки зрения именованных и не именованных групп в регулярном выражении:
- Если есть какие-либо именованные аргументы, они будут использоваться, игнорируя не именованные аргументы.
- В противном случае, все не именованные аргументы будут переданы как позиционные аргументы.
В обоих случаях любые дополнительные именованные аргументы, которые были переданы в соответствии с Передача дополнительных опций функциям представлений (ниже), также будут переданы представлению.
Что ищет 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.
Захваченные аргументы всегда являются строками
Каждый захваченный аргумент отправляется представлению как обычная строка Python, независимо от типа сопоставления, которое выполняет регулярное выражение. Например, в этой строке URLconf:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
-
…the year argument passed to views.year_archive() will be a string, - не целое число, даже если
[0-9]{4}будет соответствовать только строкам целых чисел.
Указание значений по умолчанию для аргументов представлений
Удобный трюк заключается в указании параметров по умолчанию для аргументов ваших представлений. Вот пример URLconf и представления:
# URLconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>[0-9]+)/$', 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 экземпляров url().
Обработка ошибок
Когда 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.conf.urls import include, url
urlpatterns = [
# ... snip ...
url(r'^community/', include('django_website.aggregator.urls')),
url(r'^contact/', include('django_website.contact.urls')),
# ... snip ...
]
Обратите внимание, что регулярные выражения в этом примере не имеют $ (символа совпадения с концом строки), но содержат конечный слэш. Всякий раз, когда Django сталкивается с include() (django.conf.urls.include()), он обрезает часть URL, соответствующую этой точке, и отправляет оставшуюся строку включенному URLconf для дальнейшей обработки.
Другой вариант — включение дополнительных шаблонов URL с помощью списка экземпляров url(). Например, рассмотрим этот URLconf:
from django.conf.urls import include, url
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
url(r'^reports/$', credit_views.report),
url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report),
url(r'^charge/$', credit_views.charge),
]
urlpatterns = [
url(r'^$', main_views.homepage),
url(r'^help/', include('apps.help.urls')),
url(r'^credit/', include(extra_patterns)),
]
В этом примере URL /credit/reports/ будет обрабатываться представлением Django credit_views.report().
Это можно использовать для удаления избыточности из URLconf, где один префикс шаблона используется повторно. Например, рассмотрим этот URLconf:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/history/$', views.history),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/edit/$', views.edit),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/discuss/$', views.discuss),
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/permissions/$', views.permissions),
]
Мы можем улучшить это, указав общий префикс пути только один раз и сгруппировав отличающиеся суффиксы:
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
url(r'^history/$', views.history),
url(r'^edit/$', views.edit),
url(r'^discuss/$', views.discuss),
url(r'^permissions/$', views.permissions),
])),
]
Захваченные параметры
Включенный URLconf получает любые захваченные параметры из родительских URLconf, поэтому следующий пример допустим:
# In settings/urls/main.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
]
# In foo/urls/blog.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.blog.index),
url(r'^archive/$', views.blog.archive),
]
В приведённом выше примере захваченная "username" переменная передаётся включённому URLconf, как ожидалось.
Вложенные аргументы
Регулярные выражения позволяют вложенные аргументы, и Django будет их разрешать и передавать представлению. При обратном преобразовании Django будет пытаться заполнить все внешние захваченные аргументы, игнорируя любые вложенные захваченные аргументы. Рассмотрим следующие URL-шаблоны, которые необязательно принимают аргумент страницы:
from django.conf.urls import url
urlpatterns = [
url(r'blog/(page-(\d+)/)?$', blog_articles), # bad
url(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 имеет функциональность, которая позволяет передавать дополнительные аргументы функциям представлений в виде словаря Python.
Функция django.conf.urls.url() может принимать необязательный третий аргумент, который должен быть словарем дополнительных ключевых аргументов, которые нужно передать функции представления.
Например:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
В этом примере для запроса к /blog/2005/, Django вызовет views.year_archive(request, year='2005', foo='bar').
Этот метод используется в рамке агрегации для передачи метаданных и параметров представлениям.
Обработка конфликтов
Возможен URL-шаблон, который захватывает именованные ключевые аргументы и также передаёт аргументы с теми же именами в своём словаре дополнительных аргументов. В таком случае аргументы из словаря будут использоваться вместо аргументов, захваченных в URL.
Передача дополнительных параметров в include()
Аналогично, вы можете передать дополнительные параметры к include(). Когда вы передаёте дополнительные параметры в include(), каждая строка в включенном URLconf будет получать дополнительные параметры.
Например, эти два набора URLconf функционально идентичны:
Набор один:
# main.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^blog/', include('inner'), {'blogid': 3}),
]
# inner.py
from django.conf.urls import url
from mysite import views
urlpatterns = [
url(r'^archive/$', views.archive),
url(r'^about/$', views.about),
]
Набор два:
# main.py
from django.conf.urls import include, url
from mysite import views
urlpatterns = [
url(r'^blog/', include('inner')),
]
# inner.py
from django.conf.urls import url
urlpatterns = [
url(r'^archive/$', views.archive, {'blogid': 3}),
url(r'^about/$', views.about, {'blogid': 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.conf.urls import url
from . import views
urlpatterns = [
#...
url(r'^articles/([0-9]{4})/$', 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.urls import reverse
from django.http import HttpResponseRedirect
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, который позволяет вам легко развернуть более одного экземпляра админ-панели. В последующем примере мы рассмотрим идею развертывания приложения polls из руководства в двух разных местах, чтобы мы могли предоставлять одну и ту же функциональность двум разным аудиториям (авторам и издателям).
Пространство имен 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.conf.urls import include, url
urlpatterns = [
url(r'^author-polls/', include('polls.urls', namespace='author-polls')),
url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]
from django.conf.urls import url
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', 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.
from django.conf.urls import url
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
...
]
from django.conf.urls import include, url
urlpatterns = [
url(r'^polls/', include('polls.urls')),
]
URL-адреса, определённые в polls.urls будут иметь пространство имен приложения polls.
Во-вторых, вы можете включить объект, содержащий данные вложенного пространства имён. Если вы include() список объектов url(), URL-адреса, содержащиеся в этом объекте, будут добавлены в глобальное пространство имён. Однако вы также можете include() кортеж из двух элементов, содержащий:
(<list of url() instances>, <application namespace>)
Например:
from django.conf.urls import include, url
from . import views
polls_patterns = ([
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
], 'polls')
urlpatterns = [
url(r'^polls/', include(polls_patterns)),
]
Это включит указанные шаблоны URL в заданное пространство имен приложения.
Пространство имен экземпляра можно указать с помощью аргумента namespace функции include(). Если пространство имён экземпляра не указано, оно по умолчанию будет совпадать с пространством имён приложения включённого URLconf. Это означает, что оно также будет стандартным экземпляром для этого пространства имён.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.11/topics/http/urls/