Django 2.0 introduced a new way to define URLs, which greatly simplifies how parameters are captured.

In earlier versions of Django, you had to use the url() method and pass a regular expressions with named capturing groups to capture URL parameters.

url(r'^posts/(?P<post_id>[0-9]+)/$', post_detail_view)

In Django 2.0, you use the path() method with path converters to capture URL parameters.

path('posts/<int:post_id>/', post_detail_view)

path() always matches the complete path, so path('account/login/') is equivalent to url('^account/login/$') .

The part in angle brackets ( <int:post_id> ) captures a URL parameter that is passed to a view. The part after the colon ( post_id ) defines the name of the parameter, the part before the colon ( int ) names a path converter.

Path converters are not only easier to read, they also bring a new feature: path converters can convert parameters to the appropriate type before passing it to the view.

Earlier versions of Django just passed the matched string to the view, meaning you had to write this:

url(r'^posts/(?P<post_id>[0-9]+)/$', post_detail_view) def post_detail_view(request, post_id): post_id = int(post_id) ...

Starting with Django 2.0, you would just write this:

path('posts/<int:post_id>') def post_detail_view(request, post_id): ...

Django 2.0 comes with five built-in converters:

str

Matches any non-empty string, excluding the path separator, ‘/’. This is the default if a converter isn’t included in the expression.

Example: 'best_product_ever!-123.html'

Returns a string ( str ).

Equivalent regular expression: [^/]+

Matches any non-empty string, excluding the path separator, ‘/’. This is the default if a converter isn’t included in the expression. Example: Returns a string ( ). Equivalent regular expression: int

Matches zero or any positive integer.

Example: '1234'

Returns an integer ( int ).

Equivalent regular expression: [0-9]+

slug

Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters.

Returns a string ( str ).

Example: 'building-your-1st-django-site'

Equivalent regular expression: [-a-zA-Z0-9_]+

uuid

Matches a formatted UUID. To prevent multiple URLs from mapping to the same page, dashes must be included and letters must be lowercase.

Returns a UUID instance ( uuid.UUID ).

Example: '075194d3-6885-417e-a8a8-6c931e272f00'

Equivalent regular expression: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}

path

Matches any non-empty string, including the path separator, ‘/’. This allows you to match against a complete URL path rather than just a segment of a URL path as with str.

Example: '/path/to/file'

Returns a string ( str ).

Equivalent regular expression: '.+'

If the pre-defined path converters don’t suit your needs, you can register custom path converters, which can do tricks like converting a URL parameter straight to a model instance. Alternatively, you can still use good ol’ regular expression by using re_path() instead of path() .

from django.urls import re_path re_path(r'posts/(?P<post_id>[0-9]+)/$', post_detail_view)

By the way, the old url() function is still available, so there is no need to change all your URL definitions right now.

I think the new path() method greatly simplifies dealing with URLs. I’ve been working with Django for more than 10 years now and still can’t remember how to define a named regular expression capturing group. Furthermore, manually doing the type conversion violates the DRY-principle.

I hope this little cheat sheet helps you during the transition to Django 2.0. Be sure to check out my follow-up post on how to create powerful custom path converters. Do you have any further question? Don’t hesitate to leave a comment below.

Correction: an earlier version of the image incorrectly listed the last regex as equivalent to slug instead of uuid. Thanks to @m_holtermann for pointing that out!