Django NoReverseMatch at - django

I have the following URLs:
url(r'^%sdform/' %(URLPREFIX), pv.dform, name='dform'),
url(r'^%sform/(P?<growl>.*)/' %(URLPREFIX), pv.dform, name='dform'),
The view code:
def dform(request, growl = None) is the method signature
The redirect code:
msg = 'test'
return redirect('dform', growl=msg)
Any idea why I get that error? I'm sending the right parameter to the right view method with the right argument name and all that.
EDIT:
Based on the answer below, I tried:
url(r'^%sdform/(P?<growl>.*)/' %(URLPREFIX), pv.dform, name='dform_message')
And changed the redirect to:
return redirect('dform_message', growl='Updated Settings')
I still get NoReverseMatch

I think your problem is that you shall not use the same names for different urls (django docu).

Related

NoReverseMatch exception - redirect with keyword arguments

I am getting a NoReverseMatch error when trying to use Django's redirect, and cannot figure out what I am doing wrong.
In views:
def addConjugatedForm(request):
#update database
return redirect('findConjugatedForms', chapter=ch.chapter, verse=verse.verse, book=b.name)
def findConjugatedForms(request, book, chapter, verse):
#return a view
In urls.py:
url(r'^findConjugatedForms/(?P<book>\w+)/(?P<chapter>\d+)/(?P<verse>\d+)/', 'findConjugatedForms'),
The url works as a url, i.e. "...findConjugatedForms/Romans/3/24" returns a page. But when a form on that page is submitted, it won't redirect back.
I have named arguments in my url (which seems to be the common problem in other questions on Stack Overflow) and the values of the kwargs seem to be correct.
Reverse for 'findConjugatedForms' with arguments '()' and keyword arguments '{'chapter': 3, 'verse': 24, 'book': u'Romans'}' not found. 0 pattern(s) tried: []
What am I missing?
redirect uses reverse internally. You need to define a viewname for the url, or use a Python path or pass a callable object:
url(r'^findConjugatedForms/(?P<book>\w+)/(?P<chapter>\d+)/(?P<verse>\d+)/',
'findConjugatedForms',
name='findConjugatedForms') # Define a name
Besides, add a suffix '$' into the pattern to prevent the url from matching other urls that starts with findConjugatedForms/book/chapter/verse/

Passing an attribute to a view, default attribute not working

Here is my url :
url(r'^test/$|test/(\d+)', views.test_page)
So with the django runserver fired I can enter 127.0.0.1:8000/test/ or
the same url followed with a "page" number.
Here is a simplified version of my view :
def test_page(request, pagenumber):
paginator = Paginator(Test.objects.all(), 5)
page = 1
if pagenumber:
page = pagenumber
posts = paginator.page(page)
That works but is kinda inefficient. So I modified it to :
def test_page(request, page=1):
paginator = Paginator(Test.objects.all(), 5)
posts = paginator.page(page)
Which is nicer, works when I specify a page number in the url but when
I just enter 127.0.0.1:8000/test/ it doesn't. I got a :
Exception Type: TypeError
Exception Value: int() argument must be a string or a number,
not 'NoneType'
Exception Location: /usr/lib/python2.7/site-packages/django/core/
paginator.py in validate_number, line 23
why doesn't the attribute page take the default value 1 when I don't
specify any page number ?
For things like page numbers, it's better to use GET parameters, ie the form /test/?page=1. You do this directly in the view via request.GET.get('page'), so the urlconf is just r'^test/$.
Do a check to see if the function parameter page is None in the code. If it is set the value to be 1. Instead of relying on the function to default it.
I have never seen a url entry written that way.
Could you try something like:
To pass a named argument I think you have to specify that arguments name in your urls.py , it doesn't look like you're doing that now.
(?P<page>\d+)/$ this is the way django recommends to pass defualt arguments. https://docs.djangoproject.com/en/dev/topics/http/urls/#notes-on-capturing-text-in-urls
I would try this:
def test_page(request, **kwargs):
page = kwargs.get('pagenumber', 1)
paginator = Paginator(Test.objects.all(), 5)
posts = paginator.page(page)
No shell around so I couldn't test this code.
Please do not try to assign a default value to the argument "page" which you are passing in the function call. Just keep it as:
def test_page(request, page):
Please do try it, and write the url as:
url(r'^test/(?P<page>\d+)/$', views.test_page)

Can I pass non-URL definition view keyword to a view function when redirecting?

NoReverseMatch at /natrium/script/4c55be7f74312bfd435e4f672e83f44374a046a6aa08729aad6b0b1ab84a8274/
Reverse for 'run_details' with arguments '()' and keyword arguments '{'script_text': u'print "happy"', 'run_id': '6b2f9127071968c099673254fb3efbaf'}' not found.
This is an excerpt of my views.py
run_id = new_run.run_id
if not run_id:
raise AssertionError("bad run id")
# I tried with args=[run_id, clean['script_text']] too
return HttpResponseRedirect(reverse('run_details', kwargs={'run_id':run_id, 'script_text':clean['script_text']}))
which in turns calling this view function
def run_details(request, run_id, script_text):
"""
Displays the details of a given run.
"""
run = Run(run_id)
run.update(request.user)
codebundle = CodeBundle(run.cbid)
codebundle.update(request.user)
return render_response(request, "graphyte/runs/run_script.html",
{'run':run, 'codebundle':codebundle, 'files':run.artifacts, 'bundle':codebundle,
'source_code': script_text
})
Now this is my urls.py. The actual redirect views is in another app (kinda insane, but whatever...).
urlpatterns = patterns("webclient.apps.codebundles.views",
# many.....
url(r"^cb/newfolder/$", 'codebundle_newfolder', name="codebundle_newfolder"),
)
urlpatterns += patterns('webclient.apps.runs.views',
url(r"^run_details/(?P<run_id>\w+)/$", 'run_details', name="run_details"),)
This is getting really nasty for the last three hours. I am not sure what's going on. Can someone help me debug this?
Thanks.
The original plan did not have script_text, and I used args=['run_id'] only. It works. In other words, remove script_text from the two views everything will work.
EDIT
Sorry for the confusion. Script text is just a context variable that I need to pass to the reverse destination, and from there I render my template. The URLs should only display the run_id.
No, you can't really pass an 'extra keyword' to the view function when redirecting. I'll try to explain why.
When you return HttpResponseRedirect, Django returns a response with a 302 status code, and the new location.
HTTP/1.1 302 Found
Location: http://www.example.com/new-url/
Your browser will then usually fetch the new url, but that's a separate request. If your view needs a keyword, it needs to be included in that response somehow, unless you store state in the session. Your two options are
Include the extra keyword in the url:
http://www.example.com/new-url/keyword-value/
Include the extra keyword as a GET parameter
http://www.example.com/new-url/?keyword=keyword-value.
Then in your view, grab the keyword with keyword=request.GET['keyword']. Note that the keyword is no longer a kwarg in the view signature.
A third approach is to stick the keyword into the session before you redirect, then grab it out the session in the redirected view. I would advise against doing this because it's stateful and can cause odd results when users refresh pages etc.
Your run_details url doesn't accept a kwarg named script_text at all -- remove that from your reverse kwargs.

Why doesn't this django code work?

urls.py
url(r'^some/page/$', views.some_page,
{'template_name': 'some/page.html'},
name='some_page'),
views.py
url = request.build_absolute_uri(reverse('some_page')).lower()
response = HttpResponseRedirect(url)
return response
Question:
Why doesn't this code work?
url = request.build_absolute_uri(reverse('some_page',
kwargs={"template_name": "another/page.html"})).lower()
I'm using django 1.2 on google appengine. Since I get the same error for any kind of typo/mistake, I didn't think it was useful to paste that error message here.
Thanks.
Because reverse expects the arguments to “fill in” regular expressions in the url. So reverse('some_page') should work.
What do you expect it to do?

Reverse Not Found: Sending Request Context in from templates

N.B This question has been significantly edited before the first answer was given.
Hi,
I'm fairly new to django, so apologies if I'm missing something obvious.
I've got a urls.py file that looks like this:
urlpatterns = patterns(
'',
(r'^$', 'faros.lantern.views.home_page'),
(r'^login/$', 'django.contrib.auth.views.login'),
(r'^logout/$', 'django.contrib.auth.views.logout'),
(r'^about/$', 'faros.lantern.views.about_page_index', {}, 'about_page_index'),
(r'^about/(?P<page_id>([a-z0-9]+/)?)$', 'faros.lantern.views.about_page', {}, 'about_page'),
)
Views that looks like this:
def about_page_index(request):
try:
return render_to_response('lantern/about/index.html', context_instance=RequestContext(request))
except TemplateDoesNotExist:
raise Http404
def about_page(request, page_id):
page_id = page_id.strip('/ ')
try:
return render_to_response('lantern/about/' + page_id + '.html', context_instance=RequestContext(request))
except TemplateDoesNotExist:
raise Http404
And a template that includes this:
Contact
Contact
I'm getting this error message:
Caught an exception while rendering: Reverse for '<function about_page at 0x015EE730>' with arguments '()' and keyword arguments '{'page_id': u'contact'}' not found. The first reverse works fine (about_page_index), generating the correct URL without error messages.
I think this is because the request argument to the about_page view (request) is used, so I need to pass it in when I generate the URL in my template. Problem is, I don't know how to get to it, and searching around isn't getting me anywhere. Any ideas?
Thanks,
Dom
p.s. As an aside, does that method of handling static "about" type pages in an app look horrific or reasonable? I'm essentially taking URLs and assuming the path to the template is whatever comes after the about/ bit. This means I can make the static pages look like part of the app, so the user can jump into the about section and then right back to where they came from. Comments/Feedback on whether this is djangoic or stupid appreciated!
If I guess correctly from the signature of your view function (def about_page(request, page_id = None):), you likely have another URL configuration that points to the same view but that does not take a page_id parameter. If so, the django reverse function will see only one of these, and it's probably seeing the one without the named page_id regex pattern. This is a pretty common gotcha with reverse! :-)
To get around this, assign a name to each of the url patterns (see Syntax of the urlpatterns variable). In the case of your example, you'd do:
(r'^about/(?P<page_id>([a-z]+/)?)$', 'faros.lantern.views.about_page',
{}, 'about_with_page_id')
and then in the template:
Contact
Edit
Thanks for posting the updated urls.py. In the url template tag, using the unqualified pattern name should do the trick (note that I'm deleting the lantern.views part:
Contact
Contact
Edit2
I'm sorry I didn't twig to this earlier. Your pattern is expressed in a way that django can't reverse, and this is what causes the mismatch. Instead of:
r'^about/(?P<page_id>([a-z]+/)?)$'
use:
r'^about/(?P<page_id>[a-z0-9]+)/$'
I created a dummy project on my system that matched yours, reproduced the error, and inserted this correction to success. If this doesn't solve your problem, I'm going to eat my hat! :-)