[python] Django optional url parameters

I have a Django URL like this:

url(
    r'^project_config/(?P<product>\w+)/(?P<project_id>\w+)/$',
    'tool.views.ProjectConfig',
    name='project_config'
),

views.py:

def ProjectConfig(request, product, project_id=None, template_name='project.html'):
    ...
    # do stuff

The problem is that I want the project_id parameter to be optional.

I want /project_config/ and /project_config/12345abdce/ to be equally valid URL patterns, so that if project_id is passed, then I can use it.

As it stands at the moment, I get a 404 when I access the URL without the project_id parameter.

This question is related to python django django-views django-urls

The answer is


Even simpler is to use:

(?P<project_id>\w+|)

The "(a|b)" means a or b, so in your case it would be one or more word characters (\w+) or nothing.

So it would look like:

url(
    r'^project_config/(?P<product>\w+)/(?P<project_id>\w+|)/$',
    'tool.views.ProjectConfig',
    name='project_config'
),

Use ? work well, you can check on pythex. Remember to add the parameters *args and **kwargs in the definition of the view methods

url('project_config/(?P<product>\w+)?(/(?P<project_id>\w+/)?)?', tool.views.ProjectConfig, name='project_config')

Django = 2.2

urlpatterns = [
    re_path(r'^project_config/(?:(?P<product>\w+)/(?:(?P<project_id>\w+)/)/)?$', tool.views.ProjectConfig, name='project_config')
]

Thought I'd add a bit to the answer.

If you have multiple URL definitions then you'll have to name each of them separately. So you lose the flexibility when calling reverse since one reverse will expect a parameter while the other won't.

Another way to use regex to accommodate the optional parameter:

r'^project_config/(?P<product>\w+)/((?P<project_id>\w+)/)?$'

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.


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


Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to django

How to fix error "ERROR: Command errored out with exit status 1: python." when trying to install django-heroku using pip Pylint "unresolved import" error in Visual Studio Code Is it better to use path() or url() in urls.py for django 2.0? Unable to import path from django.urls Error loading MySQLdb Module 'Did you install mysqlclient or MySQL-python?' ImportError: Couldn't import Django Django - Reverse for '' not found. '' is not a valid view function or pattern name Class has no objects member Getting TypeError: __init__() missing 1 required positional argument: 'on_delete' when trying to add parent table after child table with entries How to switch Python versions in Terminal?

Examples related to django-views

Unable to import path from django.urls Class has no objects member The view didn't return an HttpResponse object. It returned None instead django - get() returned more than one topic __init__() got an unexpected keyword argument 'user' How can I get the username of the logged-in user in Django? Django DoesNotExist How do I call a Django function on button click? Django optional url parameters Update only specific fields in a models.Model

Examples related to django-urls

Is it better to use path() or url() in urls.py for django 2.0? Django URLs TypeError: view must be a callable or a list/tuple in the case of include() What is a NoReverseMatch error, and how do I fix it? Django URL Redirect Django optional url parameters Difference between static STATIC_URL and STATIC_ROOT on Django Django - after login, redirect user to his custom page --> mysite.com/username Using {% url ??? %} in django templates Getting Django admin url for an object