Диспетчер 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.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.
Примеры запросов:
- Запрос к
/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/ будет обрабатываться credit_views.report() представлением Django.
Это можно использовать для удаления избыточности из URLconf, где один префикс шаблона URL используется многократно. Например, рассмотрим этот 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 будет вставлен в ваш шаблон при использовании этого имени.
Добавление префикса к именам ваших URL, возможно, полученного из имени приложения, уменьшит вероятность коллизий. Мы рекомендуем что-то вроде myapp-comment вместо comment.
Пространства имён URL
Введение
Пространства имён URL позволяют вам уникально обращаться к именованным шаблонам URL, даже если разные приложения используют те же имена URL. Это хорошая практика для сторонних приложений всегда использовать именованные URL (как мы делали в руководстве). Аналогично, это позволяет вам обращаться к URL, если несколько экземпляров приложения развернуты. Другими словами, так как несколько экземпляров одного приложения будут использовать одни и те же именованные URL, пространства имён предоставляют способ отличить эти именованные URL.
Приложения Django, которые правильно используют пространства имён URL, могут быть развернуты более одного раза для определённого сайта. Например, django.contrib.admin имеет класс AdminSite, который позволяет вам легко развернуть более одного экземпляра админки. В последующем примере мы рассмотрим идею развертывания приложения polls из руководства в двух разных местах, чтобы мы могли предоставить ту же функциональность двум разным аудиториям (авторам и издателям).
Пространство имён URL состоит из двух частей, обе являющихся строками:
-
application namespace - Это описывает имя приложения, которое развертывается. Каждый экземпляр одного приложения будет иметь тот же пространство имён приложения. Например, приложение Django admin имеет довольно предсказуемое пространство имён приложения
'admin'. -
instance namespace - Это идентифицирует конкретный экземпляр приложения. Пространства имён экземпляров должны быть уникальными для всего вашего проекта. Однако пространство имён экземпляра может быть таким же, как пространство имён приложения. Это используется для указания по умолчанию экземпляра приложения. Например, у по умолчанию экземпляра приложения Django admin есть пространство имён экземпляра
'admin'.
Пространства имён URL задаются с помощью оператора ':'. Например, главная страница индекса приложения admin ссылается на '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 1.9:Ранее тег шаблона
urlне использовал пространство имён текущего обработанного представления, и вам приходилось устанавливать атрибут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, который зарегистрирован последним в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. Это означает, что это также будет экземпляр по умолчанию для этого пространства имён.
В предыдущих версиях вам нужно было указать как пространство имён приложения, так и пространство имён экземпляра в одном месте, либо передав их как параметры в include(), либо включив кортеж из трёх элементов, содержащий (<list of url() instances>, <application namespace>, <instance namespace>).
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.10/topics/http/urls/