Диспетчер URL

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

См. Статью Создателя Всемирной паутины Тима Бернерса-Ли в статье «Классные URI не меняются» , где приведены убедительные аргументы в пользу того, почему URL-адреса должны быть чистыми и удобными.

Обзор

Чтобы разработать URL-адреса для приложения, вы создаете модуль Python, неофициально называемый URLconf (конфигурация URL-адреса). Этот модуль представляет собой чистый код Python и является отображением между выражениями пути URL и функциями Python (вашими представлениями).

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

Django также предоставляет способ перевода URL-адресов в соответствии с активным языком. Дополнительную информацию см. В документации по интернационализации .

Как Django обрабатывает запрос

Когда пользователь запрашивает страницу с вашего сайта на Django, система следует этому алгоритму, чтобы определить, какой код Python выполнить:

  1. Django определяет используемый корневой модуль URLconf. Обычно это значение ROOT_URLCONFпараметра, но если входящий HttpRequestобъект имеет urlconf атрибут (установленный промежуточным программным обеспечением), его значение будет использоваться вместо ROOT_URLCONFпараметра.
  2. Django загружает этот модуль Python и ищет переменную urlpatterns. Это должно быть последовательность из 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Атрибут класса, в виде строки.

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

  • Метод, который обрабатывает преобразование типа Python в строку для использования в URL. Он должен подняться, если он не может преобразовать данное значение. A интерпретируется как несоответствие и, как следствие, будет повышаться, если не совпадет другой шаблон URL.to_url(self, value)ValueErrorValueErrorreverse()NoReverseMatch

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

    ValueErrorДобавлена поддержка повышения, чтобы указать, что совпадения нет.

Например:

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=3URLconf будет искать 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значение, которое было захвачено.

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

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

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

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

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

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

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

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

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

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

Переменные:

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

В любой момент вы urlpatternsможете «включить» другие модули URLconf. По сути, это «укореняет» набор URL-адресов ниже других.

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

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)),
]

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

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

# 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, как и ожидалось.

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

В URLconfs есть ловушка, которая позволяет передавать дополнительные аргументы функциям просмотра в виде словаря 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-адресов, которые со временем устареют.

Другими словами, нужен СУХИЙ механизм. Среди других преимуществ это позволит эволюционировать дизайн 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: The get_absolute_url()method.

Примеры

Снова рассмотрим эту запись 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 а другое приложение делает то же самое, reverse()найденный URL-адрес зависит от того, какой шаблон последним находится в 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 состоит из двух частей, каждая из которых является строкой:

пространство имен приложения
Это описывает имя развертываемого приложения. Каждый экземпляр одного приложения будет иметь одно и то же пространство имен приложения. Например, приложение администратора Django имеет в некоторой степени предсказуемое пространство имен приложения 'admin'.
пространство имен экземпляра
Это идентифицирует конкретный экземпляр приложения. Пространства имен экземпляров должны быть уникальными для всего вашего проекта. Однако пространство имен экземпляра может быть таким же, как пространство имен приложения. Это используется для указания экземпляра приложения по умолчанию. Например, экземпляр администратора Django по умолчанию имеет пространство имен экземпляра 'admin'.

URL-адреса в пространстве имен указываются с помощью ':'оператора. Например, ссылка на главную страницу индекса приложения администратора выполняется с помощью 'admin:index'. Это указывает на пространство имен 'admin'и именованный URL 'index'.

Пространства имен также могут быть вложенными. Именованный URL-адрес 'sports:polls:index'будет искать шаблон, названный 'index'в пространстве имен 'polls', которое само определено в пространстве имен верхнего уровня 'sports'.

Обращение URL-адресов с пространством имен

Когда 'polls:index'для разрешения задан URL-адрес с пространством имен (например ), 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 и включенные URLconfs

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

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

Copyright ©2021 All rights reserved