Can someone please explain how you can write a url pattern and view that allows optional parameters? I\'ve done this successfully, but I always break the url template tag.
Others have demonstrated the way to handle this with two separate named URL patterns. If the repetition of part of the URL pattern bothers you, it's possible to get rid of it by using include():
url(r'^so/(?P<required>\d+)/', include('myapp.required_urls'))
And then add a required_urls.py file with:
url(r'^$', 'myapp.so', name='something')
url(r'^(?P<optional>.+)/$', 'myapp.so', name='something_else')
Normally I wouldn't consider this worth it unless there's a common prefix for quite a number of URLs (certainly more than two).
Depending on your use case, you may simply want to pass a url parameter like so:
url/?parameter=foo
call this in your view:
request.REQUEST.get('parameter')
this will return 'foo'
I generally make two patterns with a named url:
url(r'^so/(?P<required>\d+)/$', 'myapp.so', name='something'),
url(r'^so/(?P<required>\d+)/(?P<optional>.*)/$', 'myapp.so', name='something_else'),
Django urls are polymorphic:
url(r'^so/(?P<required>\d+)/$', 'myapp.so', name='sample_view'),
url(r'^so/(?P<required>\d+)/(?P<optional>.*)/$', 'myapp.so', name='sample_view'),
its obious that you have to make your views like this:
def sample_view(request, required, optional = None):
so you can call it with the same name and it would work work url resolver fine. However be aware that you cant pass None as the required argument and expect that it will get you to the regexp without argument:
Wrong:
{% url sample_view required optional %}
Correct:
{% if optional %}
{% url sample_view required optional %}
{% else %}
{% url sample_view required %}
{% endif %}
I dont know whether this is documented anywhere - I have discovered it by accident - I forgot to rewrite the url names and it was working anyway :)
Why not have two patterns:
(r'^so/(?P<required>\d+)/(?P<optional>.*)/$', view='myapp.so', name='optional'),
(r'^so/(?P<required>\d+)/$', view='myapp.so', kwargs={'optional':None}, name='required'),
in views.py you do simple thing.
def so(request, required, optional=None):
And when you dont get optional param in url string it will be None in your code.
Simple and elegant :)