I have a problem with the redirect of Django 1.4.3
#-*- coding: utf-8 -*-
from django.http import HttpResponse, Http404
from django.shortcuts import redirect
def redirect_test(request):
print("redirect_test() called.")
return redirect('redirectionFunc')
def redirectionFunc(request):
return HttpResponse("You have been redirected.")
My url is :
url(r'^redirectTest/$', 'redirect_test')
When I try to open
http://xxx/blogz/redirectTest
I got the following error :
NoReverseMatch at /blogz/redirectTest/
Reverse for 'redirectionFunc' with arguments '()' and keyword arguments '{}' not found.
Whereas the terminal I have :
redirect_test() called.
What's wrong ??
The 'redirect' method, takes the python path to the url, or the name of the url.
In the first case, if your "redirect_func" view is in app/views.py, your code should be:
return redirect('app.views.redirect_func')
If you want to name your url, for example "redirect_test", in your url configuration you should give the name parameter to the url method:
url(r'^redirectTest/$', 'app.views.redirect_func', name='redirect_test')
Then you can call redirect with the name of your url:
return redirect('redirect_test')
You can check the documentation on naming urls here
Related
My Django (2.2.5) app has the following urls.py:
from django.urls import path
from django.urls.conf import re_path
from django.views.generic.base import TemplateView
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from . import views
urlpatterns = [
re_path('^$|signin', TemplateView.as_view(template_name='signin.html'), name='signin'),
path('forgot', TemplateView.as_view(template_name='forgot.html'), name='forgot_pass'),
path('app', TemplateView.as_view(template_name='core.html'), name='core'),
path('try_signin', views.try_signin, name='try_signin'),
] + staticfiles_urlpatterns()
The first 3 rules work fine and serve up the respective HTML content. The 4th rule is for a POST request, but the request causes the following error:
Method Not Allowed (POST): /try_signin
Method Not Allowed: /try_signin
[30/Sep/2019 14:20:38] "POST /try_signin HTTP/1.1" 405 0
However if I reorder the URL rules so that the POST rule comes first, then it works fine. There's no conflict in the rules that I can see. I'm new to Django and still learning but I'd like to understand why re-ordering the rules avoids the error, or if there's something else I'm doing/not doing that caused the error.
This is my views.py:
from django.http.response import JsonResponse
from time import sleep
import logging
import json
log = logging.getLogger(__name__)
def try_signin(request):
user_email = request.POST.get('user', None)
password = request.POST.get('pass', None)
log.info("Signin attempt ==> [%s] [%s]" % (user_email, password))
sleep(2)
data = {
'success': False
}
log.info("Returning response ==> %s" % json.dumps(data))
return JsonResponse(data)
Also, adding #require_POST decorator to the try_signin function above still causes the error. As I said earlier, it does work if I reorder the rule to appear first in url_patterns.
re_path('^$|signin', ...) matches the url /try_signin. So when you POST to this URL, it goes to the TemplateView for signin.html which only accepts GET requests.
For my index page I want to show one page if the user is logged in and redirect to the login page if the user is not logged in. I do this with the following view code:
from __future__ import unicode_literals
from django.shortcuts import render_to_response, redirect
from django.contrib.auth.views import login
def index(request):
if not request.user is None and request.user.is_authenticated():
return render_to_response('foo/index.html')
else :
return redirect(login)
However I get the following warning:
RemovedInDjango110Warning: Reversing by dotted path is deprecated (django.contrib.auth.views.login)
All I have found on the topic is this question but although it seems vaguely related I can't understand how to apply it to my problem.
What does "Reversing by dotted path" mean? And where do I do it and how should it be done instead?
EDIT: I thought those lines where the problem but seems to not be the case. So the question is still similar but more general:
What does "Reversing by dotted path" mean? How do I figure out where I do it? And what should be done instead?
I agree that the 'Reversing by dotted path is deprecated' message is a bit confusing in this case.
Say you have:
url(r'^login/$', views.login, name='login-page'),
The deprecation warning is saying that you should use the url name 'login-page' instead of the dotted path, 'django.contrib.auth.views.login' when you reverse urls.
In your case, you are reversing urls when you use the redirect shortcut. When you do
return redirect(login)
the callable login is converted to a string 'django.contrib.auth.views.login' and the string is reversed, triggering the warning.
You can stop the warning by changing that line to:
return redirect('login-page')
You may then be able to remove from django.contrib.auth.views import login if it is not used anywhere else.
Note that the idiomatic way to write your view would be to use login_required and render:
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
#login_required
def index(request):
return render(request, 'foo/index.html')
views.py:
def demo(request, **kwargs):
print response
......
def test(request):
......
kwargs = {'response': response}
return redirect('demo', **kwargs)
urls.py:
from django.conf.urls import patterns, url
from django.contrib.sitemaps.views import sitemap
urlpatterns = patterns('clients.views',
url(r'^test/', 'test', name='test'),
url(r'^demo/', 'demo', name='demo'),
)
Why I have this error:
NoReverseMatch at /test/
Reverse for 'demo' with arguments '()' and keyword arguments
'{'response': {u'status': u'ok'}}' not found.
Request Method: POST Request URL: http ://127.0.0.1:8000/test/
When using the redirect() shortcut you're actually doing a HttpResponseRedirect() and therefore need not to include the response in your kwargs.
Furthermore if you would like to redirect with keyworded arguments then the call would be
redirect('/myurl/', momma="im comin' home")
or
redirect('/myurl/', kwargs={'loads_a_kwargs':'cowboy'})
The error you're getting is because your regexp url(r'^demo/', 'demo', name='demo') does not accept any parameters. Also, normally you would end all your url regexes with $ to denote that the capturing should stop.
Thats error simply been raised not from your test view but from your demo view. As per url reverse matching .. demo url must match to the demo view function parameters.
for example : url : demo/ should be demo/<response>
And In case you don't want to change the url pattern then make your response as GET parameter to demo view.
When you say redirect('demo', **kwargs), internally its trying to find the urlpattern demo/(?P<response>\d+). Actually it could be either \d+ or \w+ or whatever. But you don't have this urlpattern defined and so its failing.
So, it will pass if you define such url pattern. But another problem with your code is that response in kwargs is a dictionary and there is no way you can capture a dictionary in the url pattern.
Any particular reason you want to redirect to demo along with status code?
NoReverseMatch Exception Occurs when a matching URL in your URLconf cannot be identified based on the parameters you have given. Refer the django Docs https://docs.djangoproject.com/en/dev/ref/exceptions/#noreversematch
I am looking at your url.py You didn't included $
url(r'^test/$', 'test', name='test'),
I am trying to redirect the user to edit details of a task after task submission, but am having troubles redirecting to a page based on the newly created pk. Each view works without the return HttpResponseRedirect line. I have also tried arge=(instance.id) and kwargs=(instance.id) for the variable.
views.py
...
from django.http import HttpResponseRedirect, HttpResponseServerError, HttpResponseForbidden, Http404, HttpResponse
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response, get_object_or_404,render
...
def new_task(request):
...
...
task.save()
instance = task.save()
return HttpResponseRedirect(reverse('task_values', instance.id))
def task_values(request, task_id):
...
urls.py
from django.conf.urls.defaults import patterns, include, url
from django.http import HttpResponseRedirect
from django.views.generic.simple import direct_to_template
urlpatterns += patterns('core.views_entry',
#Task viewing/editing
(r'^task/(?P<task_id>\d+)/$','task_values'),
(r'^enter/$','new_task'),
return HttpResponseRedirect(reverse('task_values', kwargs={'task_id': instance.id}))
Also note that you don't need to save the task twice.
Edit OK, there's another problem. You haven't given your URLs specific names, which means that the only way to identify them is to pass the fully qualified view name:
reverse('core.views_entry.task_values', kwargs=...)
Or, better, use the the url() function to name your URL:
url(r'^task/(?P<task_id>\d+)/$','task_values', name='task_values'),
and you can use the original version I gave above.
Note that the error isn't telling you it's going to enter/<id>/, just that in that view it's trying to create the reverse URL for the redirection and failing.
I have a website where some pages are edited by hand. When one of those templates is missing, it just means that the page is not present, so I would like to display an Error 404.
Instead I get an exception TemplateDoesNotExist.
Is there a way to tell Django to display an error 404 whenever it does not find a template?
If you want this behaviour for all views on your site, you might want to write your own middleware with a process_exception method.
from django.template import TemplateDoesNotExist
from django.views.defaults import page_not_found
class TemplateDoesNotExistMiddleware(object):
"""
If this is enabled, the middleware will catch
TemplateDoesNotExist exceptions, and return a 404
response.
"""
def process_exception(self, request, exception):
if isinstance(exception, TemplateDoesNotExist):
return page_not_found(request)
If you have defined your own handler404 you would need to replace page_not_found above. I'm not immediately sure how you could convert the string handler404 into the callable required in the middleware..
To enable your middleware, add it to MIDDLEWARE_CLASSES in settings.py. Be careful of the position where you add it. The standard Django middleware warning applies:
Again, middleware are run in reverse order during the response phase, which includes process_exception. If an exception middleware returns a response, the middleware classes above that middleware will not be called at all.
put the return of the response in the view (or whereever the template is rendered) in a try-except block:
from django.http import Http404
from django.shortcuts import render_to_response
from django.template import TemplateDoesNotExist
def the_view(request):
...
try:
return render_to_response(...)
except TemplateDoesNotExist:
raise Http404
Off the top of my head, but if you set DEBUG=False in your settings, won't you get a 404 then on every error (including TemplateNotFound)?