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.