Spec-Zone.ru › Django 3.0

Диспетчер 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. Она должна представлять собой последовательность последовательность экземпляров django.urls.path() и/или django.urls.re_path().
  3. Django последовательно перебирает каждый шаблон URL и останавливается на первом, который соответствует запрошенному URL, сопоставляя его с path_info.
  4. Как только один из шаблонов URL совпадет, Django импортирует и вызывает заданное представление, которое является функцией Python (или представлением на основе класса). Представлению передаются следующие аргументы:

    • Экземпляр HttpRequest.
    • Если сопоставленный шаблон URL не содержал именованных групп, то соответствия из регулярного выражения передаются как позиционные аргументы.
    • Именованные аргументы состоят из любых именованных частей, сопоставленных с выражением пути, которые предоставляются, перезаписываемые любыми аргументами, указанными в необязательном аргументе kwargs к django.urls.path() или django.urls.re_path().

      Изменено в Django 3.0:

      В более старых версиях именованные аргументы со значениями None также составлялись для не указанных именованных частей.

  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 — Соответствует любой строке-тего, состоящей из букв или цифр 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 , если не может преобразовать заданное значение. ValueError интерпретируется как отсутствие совпадения и, как следствие, пользователю отправляется ответ 404, если другой шаблон URL не совпадает.
  • Метод 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 должна быть последовательностью экземпляров 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 под другими 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.

END_OF_DOCUMENT_MARKER

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

Пространство имен 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 , который зарегистрирован последним в 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() пару из двух элементов, содержащую:

(<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/3.0/topics/http/urls/

Spec-Zone.ru

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