Диспечер 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, что строка является «сырой» — что в строке не нужно экранировать ничего.
Примеры запросов:
- Запрос к
/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, а также имя домена.
Например, в запросе к http://www.example.com/myapp/ URLconf будет искать myapp/.
В запросе к http://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 не повлияет.
Значения должны быть вызываемыми объектами или строками, представляющими полный импортный путь к представлению, которое должно вызываться для обработки текущей ситуации с ошибкой.
Переменные:
-
handler400– См.django.conf.urls.handler400. -
handler403– См.django.conf.urls.handler403. -
handler404– См.django.conf.urls.handler404. -
handler500– См.django.conf.urls.handler500.
Включение других URLconf
В любой момент ваш urlpatterns может «включать» другие URLconf-модули. Это фактически «прикрепляет» набор URL под другими 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, где один префикс шаблона 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: с помощью функции
django.core.urlresolvers.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.core.urlresolvers 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, который позволяет вам легко развернуть более одного экземпляра администрирования. В последующем примере мы обсудим идею развертывания приложения опросов из учебного пособия в двух разных местах, чтобы предоставить одинаковую функциональность двум разным аудиториям (авторам и издателям).
Пространство имен 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на обрабатываемомrequest.В предыдущих версиях Django вам нужно было установить атрибут
current_appна любомContextилиRequestContext, который используется для рендеринга шаблона.Текущее приложение также можно указать вручную в качестве аргумента функции
reverse(). - Если текущего приложения нет. 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', app_name='polls')),
url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls', app_name='polls')),
]
from django.conf.urls import url
from . import views
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' %}Обратите внимание, что обращение в шаблоне требует, чтобы
current_appбыл добавлен как атрибут кrequestследующим образом:def render_to_response(self, context, **response_kwargs): self.request.current_app = self.request.resolver_match.namespace return super(DetailView, self).render_to_response(context, **response_kwargs) - Если текущего экземпляра нет — скажем, если мы рендерим страницу где-то ещё на сайте —
'polls:index'будет разрешено до последнего зарегистрированного экземпляраpolls. Поскольку нет экземпляра по умолчанию (пространство имён экземпляра'polls'), будет использоваться последний зарегистрированный экземплярpolls. Это будет'publisher-polls', поскольку он объявлен последним вurlpatterns. -
'author-polls:index'всегда будет разрешено до главной страницы экземпляра'author-polls'(и аналогично для'publisher-polls').
Если также есть экземпляр по умолчанию — скажем, экземпляр с именем 'polls' — единственное изменение по сравнению с вышеизложенным будет в случае, если текущего экземпляра нет (второй пункт в списке выше). В этом случае 'polls:index' будет разрешено до главной страницы экземпляра по умолчанию вместо экземпляра, объявленного последним в urlpatterns.
Пространства имён URL и включенные URLconfs
Пространства имён URL включённых URLconfs можно указать двумя способами.
Во-первых, вы можете предоставить пространство имён приложения и пространство имён экземпляра в качестве аргументов к include() при построении ваших шаблонов URL. Например:
url(r'^polls/', include('polls.urls', namespace='author-polls', app_name='polls')),
Это включит URL-адреса, определённые в polls.urls в пространство имён приложения 'polls', с пространством имён экземпляра 'author-polls'.
Во-вторых, вы можете включить объект, содержащий встроенные данные пространства имён. Если вы include() список объектов url(), URL-адреса, содержащиеся в этом объекте, будут добавлены в глобальное пространство имён. Однако вы также можете include() 3-кортеж, содержащий:
(<list of url() instances>, <application namespace>, <instance 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'),
]
url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))),
Это включит указанные URL-адреса в заданное пространство имён приложения и экземпляра.
Например, Django admin развертывается как экземпляры AdminSite. AdminSite объекты имеют атрибут urls: 3-кортеж, содержащий все шаблоны в соответствующем админском сайте, а также пространство имён приложения 'admin' и имя экземпляра admin. Именно атрибут urls вы include() в свои проекты urlpatterns при развертывании экземпляра admin.
Обязательно передавайте кортеж в include(). Если вы просто передадите три аргумента: include(polls_patterns, 'polls', 'author-polls'), Django не выдаст ошибки, но из-за сигнатуры include(), 'polls' будет именем пространства экземпляра, а 'author-polls' — именем пространства приложения, а не наоборот.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/topics/http/urls/