Spec-Zone.ru › Django 5.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().
  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-адресе. Он должен вызывать ValueError если не может преобразовать заданное значение. ValueError интерпретируется как отсутствие соответствия, и в результате reverse() будет вызывать NoReverseMatch, если другой шаблон 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-([0-9]+)/)?$", blog_articles),  # bad
    re_path(r"^comments/(?:page-(?P<page_number>[0-9]+)/)?$", 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, которое было захвачено.

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

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

Синтаксис переменной 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 под другими.

Например, вот выдержка из 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() сопоставляет количество аргументов и имена ключевых аргументов. Конвертеры путей также могут вызывать ValueError для указания отсутствия совпадения, см. Регистрация пользовательских конвертеров путей для получения подробностей.

Пространства имён 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. Это будет 'publisher-polls'.
  • '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")),
]

Указанные в polls.urls URL-адреса будут иметь пространство имен приложения 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/5.0/topics/http/urls/

Spec-Zone.ru

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