I am new to python and django and i have a question regarding the redirect function.
This is a reduced version of my views.py file.
def page_index(request, error_message=''):
print error_message
def add_page(request):
return redirect('page_index') # this work fine
return redirect('page_index', error_message='test') # this does not work
And here is a short version of my urls.py
urlpatterns = patterns(
'x.views',
url(r'^$', 'page_index', {'error_message': 't'}, name='page_index'),
url(r'^add/$', 'add_page', name='add_page'),
)
When i try redirecting to page_index without the keyword argument everything works fine, but when i use the kwag i get the following error message:
NoReverseMatch at /pages/add/
Reverse for 'page_index' with arguments '()' and keyword arguments '{'error_message': 'test'}' not found.
What am i doing wrong?
Short answer: There is no place in your url scheme for the 'error_message' keyword.
Longer answer:
The redirect() function is calling reverse() to build a URL; it is going to send the user's browser to that URL by returning an HTTP response with a 302 redirect status code, and the new url. Any keyword arguments that you supply to reverse() are supposed to end up as part of the url -- that's how they get communicated to the user.
In your case, though, the url for 'page_index` is just defined as '^$' -- this is the root url, which looks like 'http://yoursite.com/' in the browser.
If you want to be able to issue a redirect that contains other information, you will need to define a place for it in the url, or add it in a different way.
TwoThree ways are fairly common for this:
Use a query parameter -- this sends the message to the client explicitly; if you aren't careful, people can craft urls to make your index page say whatever they want it to.
return redirect(reverse('page-index')+"?error_message=test"))
Stash the message in the session and pull it out when the next page loads -- this requires that you have sessions configured, and keeps track of everything on the server side, rather than relying on the client to send you back the error message:
def add_page(request):
request.session['error_message'] = 'test'
return redirect('page-index')
def page_index(request):
print request.session.get('error_message','')
Use the messages framework for this -- this is preferred over ad-hoc session attributes, as long as you don't need too many 'types' of message on the same page. If all you have is a space in your template for error message, though, then this is really easy:
from django.contrib.messages import error
def add_page(request):
error(request, 'test')
return redirect('page-index')
And then in your base template, have a block like this somewhere (probably more complex than this; styled, even):
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
In bothall cases, though, you can remove the arguments from your urls.py -- the message itself is not going to be part of the path component of the URL.
urlpatterns = patterns(
'x.views',
url(r'^$', 'page_index', name='page_index'),
url(r'^add/$', 'add_page', name='add_page'),
)
You could either create a named url pattern for each error message, and pass it in the args dict, like this:
url(r'^$', 'page_index', {'error_message': 'test'}, name='test_page_index'),
or if you are willing to put the error message in the actual url you could opt for this:
url(r'(?P"<"error_message">"\w+)/^$', 'page_index', name='page_index'),
(PLEASE REMOVE THE "" around the "<" and ">", had to put them in brackets or they would be excluded form the answer, I guess everything that looks like an html tags is filtered out)
and in the view:
return redirect(reverse('page_index', args=['test']))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With