Here you will learn what are the different ways to design URLs in Django using path and re_path.

Structure of path

Import path and re_path:

# From where to import

from django.urls import path, re_path

Let's understand how url's are designed from the example below.

urlpatterns = [
    path('articles/2003/', views.special_case_2003), #1
    path('articles/<int:year>/', views.year_archive),#2
    path('articles/<int:year>/<int:month>/', views.month_archive), #3
    path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),#4
]

#1: It is a simple URL pattern to match the exact string 'articles/2003/'.

#2: In this, a parameter year of type int is passed to the view, which can be accessed like

def myview(request,year=2000):
    print(year)

#3: In this case, the year and month of type int are passed to the view.

#4: year, month of type int and slug of type slug is passed to the view.

Note: int and slug are called path converters.

Default Path converters

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

int: Matches zero or any positive integer. Returns an int.

slug: Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. For example, building-your-1st-django-site.

uuid: Matches a formatted UUID. To prevent multiple URLs from mapping to the same page, dashes must be included and letters must be lowercase. For example, 075194d3-6885-417e-a8a8-6c931e272f00. Returns a UUID instance.

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.

Creating a custom path converter

For more complex matching requirements, you can define your own path converters.

A converter is a class that includes the following:

  • regex class attribute, as a string.

  • to_python(self, value) method, which handles converting the matched string into the type that should be passed to the view function. It should raise ValueError if it can’t convert the given value. A ValueError is interpreted as no match and as a consequence, a 404 response is sent to the user.

  • to_url(self, value) method, which handles converting the Python type into a string to be used in the URL.

Create a file converters.py inside your app and paste the following:

class FourDigitYearConverter:
    regex = '[0-9]{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%04d' % value

Register custom converter classes in your URLconf using 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),
    ...
]

Using regular expressions

If the paths and converters syntax isn’t sufficient for defining your URL patterns, you can also use regular expressions. To do so, use re_path() instead of path().

In Python regular expressions, the syntax for named regular expression groups is (?Ppattern), where name is the name of the group and pattern is some pattern to match. Some of the common useful URL patterns using re_path are

# Primary Key AutoField
re_path(r'^questions/(?P<pk>\d+)/$', views.question_details, name='question_details'),

# Slug Fields
re_path(r'^posts/(?P<slug>[-\w]+)/$', views.post, name='post'),

# Slug with Primary Key
re_path(r'^blog/(?P<slug>[-\w]+)-(?P<pk>\d+)/$', views.blog_post, name='blog_post'),

# Usernames
re_path(r'^profile/(?P<username>[\w.@+-]+)/$', views.user_profile),

# Dates
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive)

# Year / Month
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),

# Year / Month / Day
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail)

That's all.