Django optional url parameters Django optional url parameters python python

Django optional url parameters


There are several approaches.

One is to use a non-capturing group in the regex: (?:/(?P<title>[a-zA-Z]+)/)?
Making a Regex Django URL Token Optional

Another, easier to follow way is to have multiple rules that matches your needs, all pointing to the same view.

urlpatterns = patterns('',    url(r'^project_config/$', views.foo),    url(r'^project_config/(?P<product>\w+)/$', views.foo),    url(r'^project_config/(?P<product>\w+)/(?P<project_id>\w+)/$', views.foo),)

Keep in mind that in your view you'll also need to set a default for the optional URL parameter, or you'll get an error:

def foo(request, optional_parameter=''):    # Your code goes here


You can use nested routes

Django <1.8

urlpatterns = patterns(''    url(r'^project_config/', include(patterns('',        url(r'^$', ProjectConfigView.as_view(), name="project_config")        url(r'^(?P<product>\w+)$', include(patterns('',            url(r'^$', ProductView.as_view(), name="product"),            url(r'^(?P<project_id>\w+)$', ProjectDetailView.as_view(), name="project_detail")        ))),    ))),)

Django >=1.8

urlpatterns = [    url(r'^project_config/', include([        url(r'^$', ProjectConfigView.as_view(), name="project_config")        url(r'^(?P<product>\w+)$', include([            url(r'^$', ProductView.as_view(), name="product"),            url(r'^(?P<project_id>\w+)$', ProjectDetailView.as_view(), name="project_detail")        ])),    ])),]

This is a lot more DRY (Say you wanted to rename the product kwarg to product_id, you only have to change line 4, and it will affect the below URLs.

Edited for Django 1.8 and above


Django > 2.0 version:

The approach is essentially identical with the one given in Yuji 'Tomita' Tomita's Answer. Affected, however, is the syntax:

# URLconf...urlpatterns = [    path(        'project_config/<product>/',        views.get_product,         name='project_config'    ),    path(        'project_config/<product>/<project_id>/',        views.get_product,        name='project_config'    ),]# View (in views.py)def get_product(request, product, project_id='None'):    # Output the appropriate product    ...

Using path() you can also pass extra arguments to a view with the optional argument kwargs that is of type dict. In this case your view would not need a default for the attribute project_id:

    ...    path(        'project_config/<product>/',        views.get_product,        kwargs={'project_id': None},        name='project_config'    ),    ...

For how this is done in the most recent Django version, see the official docs about URL dispatching.