Search code examples
pythondjangodjango-modelsdjango-viewsdjango-templates

The difference between <str:slug> and <slug:slug> in urls.py of Django application


  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?

Solution

  • Why in some cases in urls.py is used str:slug, and in other cases slug: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