Разница между <str:slug> и <slug:slug> в urls.py приложения Django

  1. Why in some cases in urls.py is used str:slug, and in other cases slug:slug? What is the difference? And which option is better to use?
  2. And can I use a category slug and then an article slug in one route?

Почему в одних случаях в urls.py используется str:slug, а в других slug:slug? В чем разница?

Конвертер path converter [Django-doc] отличается. Действительно, <str:slug> будет принимать другой набор строк (в данном случае строгое супермножество), чем те строки, которые принимает <slug:slug>.

В документации объясняется, что будет сопоставлено:

  • str - Сопоставляет любую непустую строку, исключая разделитель путей '/'. Это значение используется по умолчанию, если преобразователь не включен в выражение.

  • slug - Ищет любую строку slug, состоящую из букв или цифр ASCII, плюс символы дефиса и подчеркивания. Например, building-your-1st-django-site.

Таким образом, str будет соответствовать любой непустой строке, он будет принимать 'foo', 'straße', 'foo bar', в то время как slug преобразование пути будет существовать только как непустая последовательность ASCII букв и цифр, дефисов и подчеркиваний.

Мы также можем видеть это в реализации StringConverter [GitHub] и реализации SlugConverter [GitHub]:

class StringConverter:
    regex = '[^/]+'

    def to_python(self, value):
        return value

    def to_url(self, value):
        return value

# ⋮

class SlugConverter(StringConverter):
    regex = '[-a-zA-Z0-9_]+'

Таким образом, StringConverter будет использовать [^/]+ regex, в то время как конвертер slug будет соответствовать [-a-zA-Z0-9_]+ regex.

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

Для работы с красиво выглядящим URL был введен slug. URL, где параметр URL содержит пробел, будет заменен на ugly процентной кодировкой, так foo%20bar, тогда как в слоге обычно используется дефис, так foo-bar.

А могу ли я использовать в одном маршруте название категории, а затем название статьи?

Конечно, вы можете определить путь с:

path('<slug:category_slug>/<slug:article_slug>/', some_view)

В этом случае some_view будет принимать три параметра, так:

def some_view(request, category_slug, article_slug):
    # …
    pass
Вернуться на верх