Распределение 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 по порядку и останавливается при первом совпадении path_info с запрошенным URL.

  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/03/construire-un-site-django/ соответствует последнему шаблону. Django вызовет функцию .views.article_detail(request, year=2003, month=3, slug="construire-un-site-django")

Конвертеры пути

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

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

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

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

Конвертер - это класс, который включает в себя следующее:

  • Атрибут класса regex в виде строки.

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

  • Метод, который обрабатывает преобразование типа Python в строку для использования в URL. Он должен подняться, если не может преобразовать данное значение. A интерпретируется как несоответствие и, как следствие, будет повышаться, если не совпадет другой шаблон URL.to_url(self, value) ValueError ValueError reverse() 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

Зарегистрируйте пользовательские классы преобразования в конфигурации URL с помощью 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 для именованных групп catch:, (?P<nom>motif) где nom - имя группы, а motif - шаблон для сопоставления.

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

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 разрешает их и передает в представление. При изменении URL-адресов Django пытается заполнить все внешние захваченные параметры, игнорируя вложенные захваченные параметры. Рассмотрим следующие шаблоны URL-адресов, которые могут принимать параметр page :

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-адреса вместо простого номера страницы.

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

Конфигурации URL и сравнение содержимого

L » URLconf использует запрошенный URL как одну строку Python. Ни параметры GET, ни POST, ни имя домена не включены.

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

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

L » URLconf игнорирует метод запроса. Другими словами, все методы запросов - POST , GET и HEAD т. Д. - будут перенаправлены на ту же функцию с тем же URL.

Значения по умолчанию для параметров просмотра

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

# 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() использоваться захваченное значение.

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

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

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

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

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

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

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

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

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

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

Переменные:

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

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

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

from django.urls import include, path

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

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

Другая возможность - включить дополнительные шаблоны URL-адресов с помощью списка экземпляров path() . Например, в этой конфигурации URL:

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() .

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

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 include, как и следовало ожидать.

Передача дополнительных параметров в представление

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

Функция django.urls.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() и каждая из строк включенной конфигурации URL получит дополнительные параметры.

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

Первый набор:

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

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

Обратное разрешение URL

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

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

Другими словами, нам нужен DRY («не повторять») механизм. Одним из его преимуществ является то, что он позволяет организации URL-адресов развиваться без необходимости просматривать исходный код проекта для замены устаревших URL-адресов.

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

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

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

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

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

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

Примеры

В качестве примера возьмем эту строку конфигурации URL:

from django.urls import path

from . import views

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

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

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

<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-адрес, в котором хранятся годовые архивы статей, вам нужно будет изменить только соответствующую строку в конфигурации URL-адреса.

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

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

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

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

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

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

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

Пространства имен URL

Введение

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

Приложения Django, которые эффективно используют пространства имен URL, могут быть развернуты несколько раз для одного сайта. Например, django.contrib.admin есть класс AdminSite для развертывания более одного экземпляра интерфейса администрирования . В следующем примере мы рассмотрим идею развертывания polls учебного приложения в двух разных местах, чтобы мы могли предложить одни и те же функции двум разным аудиториям (авторам и издателям).

Пространство имен URL-адресов состоит из двух частей, которые являются строками:

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

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

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

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

При получении URL-адреса с пространством имен для разрешения (например, 'polls:index' ) Django разбивает полное имя на части и выполняет следующий поиск:

  1. Сначала Django ищет подходящее пространство имен приложения (в этом примере 'polls' ). Это создаст список экземпляров этого приложения.

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

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

  3. Если текущего приложения нет, Django ищет экземпляр приложения по умолчанию. Это соответствует экземпляру, пространство имен экземпляра которого совпадает с пространством имен приложения (в этом примере это polls вызываемый экземпляр 'polls' ).

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

  5. Если указанное пространство имен не соответствует пространству имен приложения на шаге 1, Django выполняет прямой поиск пространства имен как пространство имен экземпляра .

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

Пример

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

urls.py
from django.urls import include, path

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

from . import views

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

В этой конфигурации возможны следующие поиски:

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

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

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

    и в шаблоне:

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

  • 'author-polls:index' всегда разрешается как домашняя страница экземпляра 'author-polls' (и то же самое для 'publisher-polls' ).

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

Пространства имен URL и включенные конфигурации URL

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

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

(<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() . Если пространство имен экземпляра не определено, по умолчанию будет использоваться пространство имен приложения из включенной конфигурации URL. Это означает, что он также будет экземпляром по умолчанию для этого пространства имен.

Copyright ©2020 All rights reserved