Spec-Zone.ru › Django 1.9

Диспечер 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 выполнить:

  1. Django определяет корневой модуль URLconf, который следует использовать. Обычно это значение настройки ROOT_URLCONF, но если объект входящего HttpRequest имеет атрибут urlconf (установленный посредством обработчика запросов обработка запросов), будет использоваться его значение вместо настройки ROOT_URLCONF.
  2. Django загружает этот модуль Python и ищет переменную urlpatterns. Она должна быть списком Python из экземпляров django.conf.urls.url().
  3. Django последовательно проходит по каждому шаблону URL и останавливается на первом, который соответствует запрошенному URL.
  4. После того, как одно из регулярных выражений найдено, Django импортирует и вызывает указанное представление, которое представляет собой простую функцию Python (или представление на основе класса). Представлению передаются следующие аргументы:
    • Экземпляр HttpRequest.
    • Если сопоставленное регулярное выражение не возвращает именованные группы, то совпадения из регулярного выражения предоставляются в качестве позиционных аргументов.
    • Именованные аргументы состоят из любых именованных групп, сопоставленных регулярным выражением, перезаписанных любыми аргументами, указанными в необязательном аргументе kwargs к django.conf.urls.url().
  5. Если ни одно регулярное выражение не соответствует запросу или если во время этого процесса возникает исключение, 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, по отношению к именованным группам по сравнению с неименованными группами в регулярном выражении:

  1. Если есть какие-либо именованные аргументы, они будут использоваться, игнорируя неименованные.
  2. В противном случае все неименованные аргументы будут переданы в качестве позиционных.

В обоих случаях любые дополнительные именованные аргументы, которые были предоставлены в соответствии с Передача дополнительных параметров функциям представлений (ниже), также будут переданы представлению.

Что ищет 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, где один префикс шаблона 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, которые необязательно принимают аргумент page:

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, который позволяет вам легко развернуть более одного экземпляра админки. В последующем примере мы рассмотрим идею развертывания приложения 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 разбивает полное имя на части и затем выполняет следующие действия поиска:

  1. Сначала Django ищет совпадающее пространство имён приложения (в данном примере 'polls'). Это даст список копий этого приложения.
  2. Если определено текущее приложение, Django находит и возвращает решатель URL-адресов для этой копии. Текущее приложение можно указать с помощью аргумента current_app функции reverse().

    Тег шаблона url использует пространство имён текущего обработчика представления в качестве текущего приложения в RequestContext. Это значение по умолчанию можно переопределить, установив текущее приложение в атрибуте request.current_app.

    В предыдущих версиях Django нужно было задать атрибут current_app в любом Context или RequestContext, используемом для рендеринга шаблона.

    Ранее тег шаблона url не использовал пространство имён текущего обработчика представления, и вам приходилось устанавливать атрибут current_app в запросе.

  3. Если текущее приложение не определено, Django ищет приложение по умолчанию. Приложение по умолчанию — это копия, имеющая имя копии, соответствующее пространству имён приложения (в данном примере копия polls с именем 'polls').
  4. Если копии приложения по умолчанию нет, Django выберет последнюю развернутую копию приложения, независимо от имени копии.
  5. Если предоставленное пространство имён не соответствует пространству имён приложения на шаге 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. Это также означает, что это будет копия по умолчанию для данного пространства имён.

В предыдущих версиях вам нужно было указать и пространство имён приложения, и пространство имён копии в одном месте, либо передав их в качестве параметров функции 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.9/topics/http/urls/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API