Spec-Zone.ru › Django 2.1

Диспечер URL

Чистая и элегантная схема URL — важная деталь высококачественного веб-приложения. Django позволяет проектировать URL так, как вам нужно, без ограничений фреймворка.

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

Пример

Вот пример URLconf:

from django.urls import path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

Примечания:

  • Для захвата значения из URL-адреса используйте угловые скобки.
  • Захваченные значения могут необязательно включать тип преобразователя. Например, используйте <int:name> для захвата целочисленного параметра. Если преобразователь не указан, сопоставляется любая строка, за исключением символа /.
  • Не нужно добавлять ведущий слэш, так как каждый URL-адрес его содержит. Например, это articles, а не /articles.

Примеры запросов:

  • Запрос к /articles/2005/03/ сопоставится с третьим элементом в списке. Django вызовет функцию views.month_archive(request, year=2005, month=3).
  • /articles/2003/ сопоставится с первым шаблоном в списке, а не со вторым, потому что шаблоны проверяются в порядке следования, и первый шаблон — первая проверка, которая пройдёт. Вы можете использовать порядок, чтобы вставить специальные случаи, как этот. Здесь Django вызовет функцию views.special_case_2003(request)
  • /articles/2003 не сопоставится ни с одним из этих шаблонов, потому что каждый шаблон требует, чтобы URL заканчивался слэшем.
  • /articles/2003/03/building-a-django-site/ сопоставится с последним шаблоном. Django вызовет функцию views.article_detail(request, year=2003, month=3, slug="building-a-django-site").

Преобразователи путей

По умолчанию доступны следующие преобразователи путей:

  • str — Сопоставляет любую непустую строку, исключая разделитель путей, '/'. Это значение по умолчанию, если преобразователь не указан в выражении.
  • int — Сопоставляет ноль или любое положительное целое число. Возвращает int.
  • slug — Сопоставляет любую строку slug, состоящую из ASCII-букв или цифр, а также символов тире и подчёркивания. Например, building-your-1st-django-site.
  • uuid — Сопоставляет отформатированный UUID. Чтобы предотвратить сопоставление нескольких URL-адресов с одной и той же страницей, тире должны быть включены, а буквы — строчными. Например, 075194d3-6885-417e-a8a8-6c931e272f00. Возвращает экземпляр UUID.
  • path — Сопоставляет любую непустую строку, включая разделитель путей, '/'. Это позволяет сопоставлять весь путь URL, а не только часть пути URL, как с str.

Регистрация пользовательских преобразователей путей

Для более сложных требований к сопоставлению вы можете определить свои собственные преобразователи путей.

Преобразователь — это класс, который включает в себя следующее:

  • Атрибут класса regex, как строка.
  • Метод to_python(self, value), который обрабатывает преобразование сопоставленной строки в тип, который должен быть передан в функцию представления. Он должен вызывать ValueError в случае невозможности преобразования данного значения.
  • Метод to_url(self, value), который обрабатывает преобразование типа Python в строку, которая будет использована в URL.

Например:

class FourDigitYearConverter:
    regex = '[0-9]{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%04d' % value

Зарегистрируйте пользовательские классы преобразователей в своём URLconf, используя register_converter():

from django.urls import path, register_converter

from . import converters, views

register_converter(converters.FourDigitYearConverter, 'yyyy')

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    path('articles/<yyyy:year>/', views.year_archive),
    ...
]

Использование регулярных выражений

Если синтаксис путей и преобразователей недостаточно для определения ваших шаблонов URL, вы также можете использовать регулярные выражения. Для этого используйте re_path() вместо path().

В Python-регулярных выражениях синтаксис именованных групп регулярных выражений — (?P<name>pattern), где name — имя группы, а pattern — некоторый шаблон для сопоставления.

Вот пример URLconf из предыдущего примера, переписанный с использованием регулярных выражений:

from django.urls import path, re_path

from . import views

urlpatterns = [
    path('articles/2003/', views.special_case_2003),
    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),
]

Это делает примерно то же самое, что и предыдущий пример, за исключением:

  • Точные URL-адреса, которые будут сопоставлены, несколько более ограничены. Например, год 10000 больше не будет сопоставлен, так как целые числа лет ограничены четырьмя цифрами.
  • Каждый захваченный аргумент передаётся представлению как строка, независимо от того, какое сопоставление выполняет регулярное выражение.

При переключении с использования path() на re_path() или наоборот, очень важно понимать, что тип аргументов представления может измениться, и, следовательно, вам может потребоваться адаптировать ваши представления.

Использование безымянных групп регулярных выражений

Помимо синтаксиса именованной группы, например, (?P<year>[0-9]{4}), вы также можете использовать более короткий безымянный синтаксис, например, ([0-9]{4}).

Это использование не особенно рекомендуется, так как это облегчает случайное введение ошибок между предполагаемым значением сопоставления и аргументами представления.

В любом случае рекомендуется использовать только один стиль в заданном регулярном выражении. Когда оба стиля смешаны, любые безымянные группы игнорируются, и только именованные группы передаются функции представления.

Вложенные аргументы

Регулярные выражения позволяют вложенные аргументы, и Django будет их обрабатывать и передавать представлению. При обратном преобразовании Django будет пытаться заполнить все внешние захваченные аргументы, игнорируя любые вложенные захваченные аргументы. Рассмотрим следующие шаблоны URL, которые необязательно принимают аргумент страницы:

from django.urls import re_path

urlpatterns = [
    re_path(r'^blog/(page-(\d+)/)?$', blog_articles),                  # bad
    re_path(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

URLconf ищет в запрошенном URL-адресе как обычной строке Python. Это не включает параметры GET или POST, а также имя домена.

Например, в запросе к https://www.example.com/myapp/, URLconf будет искать myapp/.

В запросе к https://www.example.com/myapp/?page=3, URLconf будет искать myapp/.

URLconf не анализирует метод запроса. Другими словами, все методы запроса — POST, GET, HEAD, и т. д. — будут маршрутизированы к одной и той же функции для одного и того же URL.

Указание значений по умолчанию для аргументов представления

Удобный трюк — задать значения по умолчанию для аргументов ваших представлений. Вот пример URLconf и представления:

# URLconf
from django.urls import path

from . import views

urlpatterns = [
    path('blog/', views.page),
    path('blog/page<int:num>/', views.page),
]

# View (in blog/views.py)
def page(request, num=1):
    # Output the appropriate page of blog entries, according to num.
    ...

В приведённом примере оба URL-шаблона указывают на одно и то же представление — views.page — но первый шаблон не захватывает ничего из URL. Если совпадает первый шаблон, функция page() будет использовать значение по умолчанию для аргумента num, 1. Если совпадает второй шаблон, page() будет использовать значение, захваченное для num.

Производительность

Каждый регулярное выражение в urlpatterns компилируется при первом обращении к нему. Это делает систему чрезвычайно быстрой.

Синтаксис переменной urlpatterns

urlpatterns должна быть списком Python из экземпляров path() и/или re_path().

Обработка ошибок

Когда Django не может найти соответствие запрошенному URL-адресу или возникает исключение, Django вызывает представление для обработки ошибок.

Представления для этих случаев задаются четырьмя переменными. Их значения по умолчанию подойдут для большинства проектов, но дополнительная настройка возможна путём переопределения значений по умолчанию.

См. документацию по настройке представлений ошибок для получения подробностей.

Эти значения могут быть заданы в вашем корневом URLconf. Установка этих переменных в любом другом URLconf не повлияет на результат.

Значения должны быть вызываемыми объектами или строками, представляющими полный путь импорта Python к представлению, которое должно быть вызвано для обработки ошибки.

Переменные:

  • handler400 – См. django.conf.urls.handler400.
  • handler403 – См. django.conf.urls.handler403.
  • handler404 – См. django.conf.urls.handler404.
  • handler500 – См. django.conf.urls.handler500.

Включение других URLconf

В любой момент ваш urlpatterns может «включать» другие модули URLconf. Это по сути «привязывает» набор URL-адресов к другим.

Например, вот фрагмент URLconf для самого сайта Django. Он включает несколько других URLconf:

from django.urls import include, path

urlpatterns = [
    # ... snip ...
    path('community/', include('aggregator.urls')),
    path('contact/', include('contact.urls')),
    # ... snip ...
]

Когда Django сталкивается с include(), он отбрасывает ту часть URL, которая совпала до этого момента, и отправляет оставшуюся строку включённому URLconf для дальнейшей обработки.

Ещё один вариант — включить дополнительные URL-шаблоны, используя список экземпляров path(). Например, рассмотрите этот URLconf:

from django.urls import include, path

from apps.main import views as main_views
from credit import views as credit_views

extra_patterns = [
    path('reports/', credit_views.report),
    path('reports/<int:id>/', credit_views.report),
    path('charge/', credit_views.charge),
]

urlpatterns = [
    path('', main_views.homepage),
    path('help/', include('apps.help.urls')),
    path('credit/', include(extra_patterns)),
]

В этом примере URL /credit/reports/ будет обрабатываться представлением Django credit_views.report().

Это можно использовать для устранения избыточности в URLconf, где один префикс шаблона используется повторно. Например, рассмотрите этот URLconf:

from django.urls import path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/history/', views.history),
    path('<page_slug>-<page_id>/edit/', views.edit),
    path('<page_slug>-<page_id>/discuss/', views.discuss),
    path('<page_slug>-<page_id>/permissions/', views.permissions),
]

Мы можем улучшить это, указав общий префикс пути только один раз и сгруппировав различные суффиксы:

from django.urls import include, path
from . import views

urlpatterns = [
    path('<page_slug>-<page_id>/', include([
        path('history/', views.history),
        path('edit/', views.edit),
        path('discuss/', views.discuss),
        path('permissions/', views.permissions),
    ])),
]

Захваченные параметры

Включённый URLconf получает любые захваченные параметры из родительских URLconf, поэтому следующий пример верен:

# In settings/urls/main.py
from django.urls import include, path

urlpatterns = [
    path('<username>/blog/', include('foo.urls.blog')),
]

# In foo/urls/blog.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.blog.index),
    path('archive/', views.blog.archive),
]

В приведённом примере захваченная переменная "username" передаётся включённому URLconf, как ожидалось.

Передача дополнительных опций функциям представлений

URLconf имеют возможность передавать дополнительные аргументы вашим функциям представлений в виде словаря Python.

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

Например:

from django.urls import path
from . import views

urlpatterns = [
    path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]

В этом примере для запроса к /blog/2005/, Django вызовет views.year_archive(request, year=2005, foo='bar').

Этот приём используется в рамке синоптических данных для передачи метаданных и параметров представлениям.

Обработка конфликтов

Возможно, что шаблон URL захватывает именованные ключевые аргументы, а также передаёт аргументы с теми же именами в словаре дополнительных аргументов. В этом случае аргументы в словаре будут использоваться вместо аргументов, захваченных в URL.

Передача дополнительных опций к include()

Аналогично, вы можете передать дополнительные параметры к include(), и каждая строка в включённом URLconf получит дополнительные параметры.

Например, эти два набора URLconf функционально идентичны:

Набор один:

# main.py
from django.urls import include, path

urlpatterns = [
    path('blog/', include('inner'), {'blog_id': 3}),
]

# inner.py
from django.urls import path
from mysite import views

urlpatterns = [
    path('archive/', views.archive),
    path('about/', views.about),
]

Набор два:

# main.py
from django.urls import include, path
from mysite import views

urlpatterns = [
    path('blog/', include('inner')),
]

# inner.py
from django.urls import path

urlpatterns = [
    path('archive/', views.archive, {'blog_id': 3}),
    path('about/', views.about, {'blog_id': 3}),
]

Обратите внимание, что дополнительные параметры всегда будут передаваться каждой строке в включённом URLconf, независимо от того, принимает ли представление этой строки эти параметры как допустимые. По этой причине этот приём полезен только если вы уверены, что каждое представление в включённом URLconf принимает передаваемые дополнительные параметры.

Обратный поиск URL-адресов

Общая потребность при работе с проектом Django — возможность получить URL-адреса в их окончательной форме, либо для встраивания в сгенерированное содержимое (URL представлений и ресурсов, URL, отображаемые пользователю и т.д.), либо для обработки потока навигации на стороне сервера (перенаправления и т.д.).

Сильно желательно избегать жёсткого кодирования этих URL-адресов (трудоёмкий, не масштабируемый и подверженный ошибкам подход). Аналогично небезопасно разрабатывать специальные механизмы для генерации URL-адресов, параллельно с дизайном, описанным в URLconf, что может привести к созданию устаревших URL-адресов со временем.

Другими словами, нужен DRY-механизм. Среди прочего, он позволит изменять дизайн URL-адресов, не просматривая весь исходный код проекта для поиска и замены устаревших URL-адресов.

Основная информация, доступная для получения URL-адреса, — это идентификатор (например, имя) представления, ответственного за его обработку. Другие необходимые данные для поиска правильного URL-адреса — тип (позиционный, ключевой) и значения аргументов представления.

Django предлагает решение, в котором маппер URL-адресов является единственным хранилищем дизайна URL-адресов. Вы передаёте ему URLconf, а затем он может использоваться в обоих направлениях:

  • Начиная с URL-адреса, запрошенного пользователем/браузером, он вызывает нужное представление Django, предоставляя необходимые аргументы со значениями, извлечёнными из URL.
  • Начиная с идентификатора соответствующего представления Django и значений аргументов, которые будут переданы ему, получить связанный URL-адрес.

Первый случай — использование, которое мы обсуждали в предыдущих разделах. Второй — то, что известно как обратный поиск URL-адресов, обратное сопоставление URL-адресов, обратный поиск URL-адресов или просто обратное преобразование URL.

Django предоставляет инструменты для выполнения обратного преобразования URL-адресов, соответствующие различным уровням, где требуются URL-адреса:

  • В шаблонах: Использование тега шаблона url.
  • В коде Python: Использование функции reverse().
  • В коде более высокого уровня, связанном с обработкой URL-адресов экземпляров моделей Django: Метод get_absolute_url().

Примеры

Рассмотрим ещё раз эту запись URLconf:

from django.urls import path

from . import views

urlpatterns = [
    #...
    path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
    #...
]

Согласно этому дизайну, URL-адрес архива, соответствующего году nnnn, — это /articles/<nnnn>/.

Вы можете получить их в коде шаблона, используя:

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

Или в коде Python:

from django.http import HttpResponseRedirect
from django.urls import reverse

def redirect_to_year(request):
    # ...
    year = 2006
    # ...
    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

Если по каким-либо причинам было решено изменить URL-адреса, где публикуется контент для ежегодных архивов статей, то вам потребуется только изменить запись в URLconf.

В некоторых сценариях, где представления являются универсальными, может существовать многозначное отношение между URL-адресами и представлениями. В этих случаях имя представления не является достаточным идентификатором для обратного преобразования URL-адресов. Прочитайте следующий раздел, чтобы узнать о решении, которое предлагает Django для этого.

Именование URL-шаблонов

Для выполнения обратного преобразования URL-адресов вам потребуются именованные URL-шаблоны, как показано в примерах выше. Строка, используемая для имени URL-адреса, может содержать любые символы. Вы не ограничены допустимыми именами Python.

При выборе имён URL-шаблонов выбирайте такие имена, которые, скорее всего, не будут совпадать с выбором имён других приложений. Если вы назовёте ваш шаблон URL comment, а другое приложение сделает то же самое, URL, который находит reverse(), зависит от того, какой шаблон находится последним в списке urlpatterns вашего проекта.

Добавление префикса к именам ваших URL-адресов, возможно, полученного из имени приложения (например, myapp-comment вместо comment), уменьшает вероятность совпадений.

Вы можете намеренно выбрать то же имя URL-адреса, что и у другого приложения, если хотите переопределить представление. Например, часто используется переопределение представления входа LoginView. Части Django и большинство сторонних приложений предполагают, что у этого представления есть шаблон URL с именем login. Если у вас есть пользовательское представление входа и вы даёте его URL имя login, reverse() найдёт ваше пользовательское представление, если оно находится в urlpatterns после включения django.contrib.auth.urls (если оно вообще включено).

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

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

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

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

  3. Если текущее приложение не определено, Django ищет приложение по умолчанию. Приложение по умолчанию — это экземпляр, у которого пространство имён экземпляра соответствует пространству имён приложения (в данном примере, экземпляр polls с именем 'polls').
  4. Если экземпляра приложения по умолчанию нет, Django выберет последний развернутый экземпляр приложения, каким бы ни было его имя экземпляра.
  5. Если указанное пространство имён не соответствует пространству имён приложения на шаге 1, Django попытается выполнить прямой поиск пространства имён как пространства имён экземпляра.

Если есть вложенные пространства имён, эти шаги повторяются для каждой части пространства имён, пока не останется только имя представления. Затем имя представления будет преобразовано в URL в найденном пространстве имён.

Пример

Чтобы продемонстрировать стратегию разрешения в действии, рассмотрим пример двух экземпляров приложения polls из руководства: один с именем 'author-polls' и один с именем 'publisher-polls'. Предположим, мы расширили это приложение, чтобы оно учитывало пространство имён экземпляра при создании и отображении опросов.

urls.py
from django.urls import include, path

urlpatterns = [
    path('author-polls/', include('polls.urls', namespace='author-polls')),
    path('publisher-polls/', include('polls.urls', namespace='publisher-polls')),
]
polls/urls.py
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    ...
]

Используя эту настройку, возможны следующие поиски:

  • Если один из экземпляров является текущим — например, если мы отображаем страницу деталей в экземпляре 'author-polls' — 'polls:index' будет преобразовано в главную страницу экземпляра 'author-polls'; т.е. оба следующих результата "/author-polls/".

    В методе представления на основе класса:

    reverse('polls:index', current_app=self.request.resolver_match.namespace)
    

    и в шаблоне:

    {% url 'polls:index' %}
    
  • Если текущий экземпляр не определен — например, если мы отображаем страницу где-то еще на сайте — 'polls:index' будет преобразовано в последний зарегистрированный экземпляр polls. Поскольку нет экземпляра по умолчанию (пространство имён экземпляра 'polls' ), будет использоваться последний зарегистрированный экземпляр polls. Это будет 'publisher-polls', так как он объявлен последним в urlpatterns.
  • 'author-polls:index' всегда будет преобразовано в главную страницу экземпляра 'author-polls' (и аналогично для 'publisher-polls').

Если также есть экземпляр по умолчанию — например, экземпляр с именем 'polls' — единственное изменение по сравнению с вышеизложенным будет в случае, когда нет текущего экземпляра (второй пункт в списке выше). В этом случае 'polls:index' будет преобразовано в главную страницу экземпляра по умолчанию, а не экземпляра, объявленного последним в urlpatterns.

Пространства имён URL и включённые URLconf

Пространства имён приложения включённых URLconf могут быть указаны двумя способами.

Во-первых, вы можете установить атрибут app_name в модуле включённого URLconf на том же уровне, что и атрибут urlpatterns . Вы должны передать фактический модуль или строку, ссылающуюся на модуль, в include(), а не сам список urlpatterns.

polls/urls.py
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    ...
]
urls.py
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
]

URL, определённые в polls.urls будут иметь пространство имён приложения polls.

Во-вторых, вы можете включить объект, содержащий встроенные данные пространства имён. Если вы include() список экземпляров path() или re_path(), URL, содержащиеся в этом объекте, будут добавлены в глобальное пространство имён. Однако вы также можете include() 2-кортеж, содержащий:

(<list of path()/re_path() instances>, <application namespace>)

Например:

from django.urls import include, path

from . import views

polls_patterns = ([
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
], 'polls')

urlpatterns = [
    path('polls/', include(polls_patterns)),
]

Это включит указанные шаблоны URL в заданное пространство имён приложения.

Пространство имён экземпляра может быть указано с помощью аргумента namespace к include(). Если пространство имён экземпляра не указано, оно будет по умолчанию равно пространству имён приложения включённого URLconf. Это означает, что это также будет экземпляр по умолчанию для этого пространства имён.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.1/topics/http/urls/

Spec-Zone.ru

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