Django Template Reverse URL Resolution Not Working - python

I have the following in my project's urls.py:
urlpatterns = patterns('',
url(r'^watches/(?P<object_id>\d+)/$', list_detail.object_detail, watch_detail, name='watch_detail'),
)
However, the following line in a template returns an error:
<li>A link</li>
It returns this error:
NoReverseMatch at /watches/
Reverse for ''watch_detail'' with arguments '(1,)' and keyword arguments '{}' not found.
This confuses me a lot, because if I run "manage.py shell" I get the following results:
>>> from django.core.urlresolvers import reverse
>>> reverse("watch_detail", args=(1,))
'/watches/1/'
>>>
Any suggestions as to what might be wrong?
Thank you.

What's the third parameter you've got in your url conf (watch_detail)? Looking at the docs, your third parameter should be a dictionary.
Should your conf file read as follows? -
urlpatterns = patterns('',
url(r'^watches/(?P<object_id>\d+)/$', 'list_detail.object_detail.watch_detail', name='watch_detail'),
)
(that's assuming your view is at list_detail/object_detail/watch_detail).
Just to clarify, you can also pass a view function instead of a string path, so your url conf could be written like -
from your_app.your_module import watch_detail
urlpatterns = patterns('',
url(r'^watches/(?P<object_id>\d+)/$', watch_detail, name='watch_detail'),
)
Where the second parameter, watch_detail, is your view function.
EDIT
If watch_detail really is a parameter then you'll need to include it in the template reverse function -
{% url 'watch_detail', 1, watch_detail %}

Related

While creating dynamic url I am getting a Reverse for 'dashboard_group' with arguments error

urls.py
urlpatterns = [
path('processes/', views.processes, name="dashboard"),
path('processes/<uuid:u_id>/', views.groups, name="dashboard_group")
]
views.py
def processes(request):
return render(request, 'processes/index.html')
def groups(request, u_id):
return render(request, 'create_instance/index.html')
The above code gives me following error - Reverse for 'dashboard_group' with arguments '('a21713b0ec29416c8fb27d4f339eabb8',)' not found. 1 pattern(s) tried: ['processes\/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\/$']
Remove uuid: from the path. Your code should look like this.
urlpatterns = [
path('processes/', views.processes, name="dashboard"),
path('processes/<u_id>/', views.groups, name="dashboard_group")
]
According to Django official documentation, the bracket may include a converter specification (like the int part of <int:section>) which limits the characters matched and may also change the type of the variable passed to the view.
django.urls functions for use in URLconfs

Django: Named Url's/ Same regex, different Names

I have a urls.py file which contains multiple urls with same named paramaters and regex but different names. When I call a view function from the template using {% url 'name' param %} it calls the function which comes first in the urls.py file in disregard to the name. Here is the content of urls.py:
urlpatterns = patterns('accountsearch.views',
url(r'^$', 'account_search', name='account_search'),
url(r'(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$','reset_password',name='reset_password'),
url(r'(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$','reset_securityquestions',name='reset_securityquestions'),
I am trying to call reset_securityquestions from the template using:
"{% url 'reset_securityquestions' account.uuid user.uuid %}">
but it calls reset_password instead.
If I change the order of urls in urls.py to this:
urlpatterns = patterns('accountsearch.views',
url(r'^$', 'account_search', name='account_search'),
url(r'(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$', 'reset_securityquestions',
name='reset_securityquestions'),
url(r'(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$', 'reset_password', name='reset_password'),
and call reset_password using:
{% url 'reset_password' account.uuid user.uuid %}
it calls the reset_security_questions function. Where am I going wrong?
Django always take firsts matching url pattern , so rewrite the urls as :
urlpatterns = patterns('accountsearch.views',
url(r'^$', 'account_search', name='account_search'),
url(r'^reset-password/(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$','reset_password',name='reset_password'),
url(r'^security-question/(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$','reset_securityquestions',name='reset_securityquestions'),
I don't understand how you are expecting Django to know which URL to use if they both have exactly the same url pattern. When the request comes in, all Django has to go on is the URL itself, and it will always try and match those in order. With your switched patterns, you'll find that the reset_password view now doesn't work.
You need to give Django some way of distinguishing between them. Usually some literal text, either as a prefix or a suffix, would be used, for example:
r'reset/(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$'
r'security/(?P<account_uuid>[a-zA-Z0-9\-]+)/(?P<user_uuid>[a-zA-Z0-9\-]+)/$'

NoReverseMatch error when using Django url template tag with optional parameters, but NOT when visiting the URL in the browser

I have a URL that needs to account for the following patterns:
localhost:8000/staffing-agencies
localhost:8000/staffing-agencies/90210 (zip code)
localhost:8000/staffing-agencies/portland-or (city-state)
When I type in any of these urls in my browser, they all work as expected. However, I'm getting a NoReverseMatch error when I try to refer to this URL from Django's url template tag.
Here are my relevant url.py files:
# From urls.py
urlpatterns = patterns('',
url(r'^', include('bos.apps.search.urls', namespace='search',
app_name='search')),
)
# From search/urls.py
urlpatterns = patterns('bos.apps.search',
url(r'^staffing-agencies/'
r'((?P<city>[a-zA-Z]+)-(?P<state>[a-zA-Z]{2}))?'
r'((?P<zip>[0-9]{5}))?$',
'views.main', name='main'),
)
I thought it might be something to do with the optional parameters, but all of these variances throw the NoReverseMatch error:
Test
Test
This variance does NOT throw an error:
Test
I'm using Django 1.6.5
This not better solution, this is one of solution
url(r'^staffing-agencies/(?P<city>[a-zA-Z]+)*-(?P<state>[a-zA-Z]{2})*?(?P<zip>[0-9]{5})*?$',
'views.main', name='main'),
in views:
def main(request, city=None, state=None, zip=None):
in html:
Test
In this case url work like this,
localhost:8000/staffing-agencies
localhost:8000/staffing-agencies/-90210 (zip code)
localhost:8000/staffing-agencies/portland-or (city-state)

Understanding django.shortcuts.redirect

I have a couple problems understanding how redirect or rather reverse really work.
In the main urls.py I have:
from django.conf.urls import patterns, include, url
from django.views.generic.simple import redirect_to
urlpatterns = patterns('',
url(r'^$', redirect_to, {'url': '/monitor/'}),
url(r'^monitor/', include('monitor.urls')),
)
and in monitors.urls I have:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('monitor.views',
(r'^$', 'index'),
(r'^abc/(?P<id>.*$)', 'abc'),
)
When you call /monitor I want to redirect it to /monitor/abc so I did:
def index(request):
return redirect("abc")
def abc(render, id=None):
return render_to_response("monitor/list.htmld", {})
But I got an NoReverseMatch exception. But when I do:
def index(request):
return redirect("abc/")
then it suddenly works.
I cannot fully understand why. Why did reverse fail with abc but not with abc/? And how does reverse know that the redirect should include monitor/ as well? What if I had in the main urls.py another app called xyz which also has a abc view?
Why did reverse fail with 'abc' but not with 'abc/'?
Because it interpreted it as a view name (and you indeed have a view named 'abc', see your monitor.urls file). This means Django will call reverse to compute the URL. The value abc/ is interpreted as an actual URL which means Django won't call reverse to determine the URL.
This also explains why reverse failed: the view with name abc also requires an argument called id. Otherwise Django won't be able to lookup the URL as there is no view called abc without parameters.
Based on the documentation you should be able to reverse the URL using:
redirect("abc", id=...)
where ... is the value of the id parameter.
And how does reverse know that the redirect should include monitor/ as well?
That is because it knows what URLs are available and 1) it knows where the view called abc is defined and 2) it knows that monitors.urls is included with monitor/ in front.
What if I had in the main urls.py another app called "xyz" which also has a "abc" view?
In that case you have to use namespaces.

Django NoReverseMatch exception with cache_page in urls.py

Question
Why does using the cache_page function in urls.py under Django 1.4 cause a NoReverseMatch error when using the url tag in a template?
Setup
views.py
from django.shortcuts import render
def index(request):
'''Display the home page'''
return render(request, 'index.html')
urls.py
Following the cache_page directions:
from django.conf.urls import patterns, include, url
from django.views.decorators.cache import cache_page
from my_project.my_app import views
urlpatterns = patterns('',
url(r'^$', cache_page(60 * 60)(views.index)),
)
index.html
{% url my_project.my_app.views.index %}
Error Message
NoReverseMatch at /
Reverse for 'my_project.my_app.views.index' with arguments '()' and keyword arguments '{}' not found.
The offending line the error message points out is, of course:
{% url my_project.my_app.views.index %}
What I've tried so far
A ton of googling and searching on SO
Simplifying code down to the example above to rule out other conflicts
Used cache_page in views.py as a decorator successfully (not recommended according to docs)
Offerings to our all-powerful Django overlords
When doing reverse, Django tries to match by
URL label
dotted path
callable
In your code, 'my_project.my_app.views.index' is dotted path, then Django would get the actual function index() and use it as the key to match the reversed URL, by looking up in the mapping dictionary django.core.urlresolvers.get_resolver(None).reverse_dict.
However, when you wrap the view.index by cache_view, the key in the mapping dictionay becomes the wrapper. Thus the lookup fails and NoReverseMatch is raised. This is inconvenient and error-prone, but I'm not sure whether it is a bug.
You could then solve this by either use URL label
url(r'^$', cache_page(60 * 60)(views.index), name='my_index'),
{# in template #}
{% url my_index %}
or used cache_page in views.py as a decorator as you mentioned.

Categories