Why in some cases in urls.py is used
str:slug
, and in other casesslug:slug
? What is the difference?
The path converter [Django-doc] is different. Indeed, the <str:slug>
will accept a different set of strings (in this case a strict superset) than the strings the <slug:slug>
will accept.
The documentation explains what will be matched:
str
- Matches any non-empty string, excluding the path separator, '/'. This is the default if a converter isn't included in the expression.
slug
- Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. For example, building-your-1st-django-site.
The str
will thus match any non-empty string, it will thus accept 'foo'
, 'straße'
, 'foo bar'
, whereas the slug
path convert will only exist as a non-empty sequence of ASCII letters and numbers and hyphens and underscores.
We can also see this in the implementation of the StringConverter
[GitHub] and the implementation of the 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_]+'
The StringConverter
will thus use the [^/]+
regex, whereas the slug converter will match with the [-a-zA-Z0-9_]+
regex.
Usually if you work with slugs, it is better to work with the slug path converter, since this will not match with non-slugs, and usually one matches with slugs, not with strings.
A slug has been introduced to work with a pretty looking URL. A URL where the URL parameter contains a space will be replaced by ugly percentage encoding, so foo%20bar
, whereas a slug will normally use a hyphen, so foo-bar
.
And can I use a category slug and then an article slug in one route?
Sure you can define a path with:
path('<slug:category_slug>/<slug:article_slug>/', some_view)
The some_view
will in that case accept three parameters, so:
def some_view(request, category_slug, article_slug):
# …
pass