In my login view function, i wanted to know if the user is redirected here after being stopped from accessing a Page
This is basically a Q & A website where user is redirected to login page if he click on write Answer link without signing In
Here is views.py of main app
from django.shortcuts import render
from django.http import request, HttpResponseRedirect, HttpResponse
# import the models
from .models import Question, Answer, Comment
# import paginator for pagination
from django.core.paginator import Paginator
# import forms
from .forms import Write_Answer_form, CommentForm
# import user
from django.contrib.auth.models import User
# import timezone for update function
from django.utils import timezone
# reverse for efficient url redirecting
from django.urls import reverse
from django.shortcuts import redirect
# Create your views here.
# i have deleted some views functions as they seems irrelavant here
def writeAns(request,questionID):
# check if the user is authenticated
if request.user.is_authenticated:
# get the Question from ID
RequestedQuestion= Question.objects.get(id= questionID)
# check if there is a post request from template
if request.method == 'POST':
# get all the form data with post request into a variable
fom= Write_Answer_form(request.POST)
if fom.is_valid():
get_save_form_data(RequestedQuestion, request, fom)
# make a string url to pass as a arguments
url= '/detail/'+ str(questionID)
return HttpResponseRedirect(url)
else:
# send blank form to template
fom= Write_Answer_form()
data= {'form':fom}
return render(request, 'writeAns.html', data)
# if user is not authenticated
else:
return redirect('login_page',args=["True"])
views.py of authentiCation app ( i want to send redirected value to login_page function )
from django.shortcuts import render
from django.http import request,HttpResponseRedirect
# for user creation & login form
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login, logout
# for user related Queries
from django.contrib.auth.models import User
from django.urls import reverse
from django.shortcuts import redirect
# imports for test purpose
from django.http import HttpResponse
# Create your views here.
# register page
def register_Page(request):
if request.method == 'POST':
form= UserCreationForm(request.POST)
if form.is_valid():
form.save()
username= request.POST['username']
password= request.POST['password1']
user= authenticate(request,username=username,password=password)
login(request,user)
return HttpResponseRedirect('/')
else:
return HttpResponse('Either the user name is not available or you may have filled the form incorrectly')
else:
form = UserCreationForm()
context= {'form':form}
return render(request,'authentication/register_Page.html',context)
# login page
def login_page(request,redirected=None):
if request.method == 'POST':
username= request.POST['username']
password= request.POST['password']
# returns user if credentials are valid
user= authenticate(request, username=username, password= password)
# check if user var contains the user
if user is not None:
login(request, user)
return redirect(reverse('Home_page'))
else:
return HttpResponse('Invalid credentials')
# check if the user is redirected
if redirected == "True":
data= {'warning':"please login first"}
return render(request,'authentication/login.html',data)
else:
return render(request,'authentication/login.html')
# logout Page
def log_out(request):
logout(request)
return HttpResponseRedirect(reverse('login_page'))
urls.py of authentiCation
from django.urls import path
from authentiCation import views
urlpatterns = [
path('register/',views.register_Page,name='register_Page'),
path('login/',views.login_page,name='login_page'),
path('logout/',views.log_out,name='logout_page'),
]
And here is the Traceback
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/writeAns/5
Django Version: 3.2
Python Version: 3.7.3
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'App_wfi_Community',
'django.contrib.humanize',
'askQuestion',
'authentiCation']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/saurav/Documents/programming_Projects/WFI-Community/App_wfi_Community/views.py", line 114, in writeAns
return redirect('login_page',args=["True"])
File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/shortcuts.py", line 41, in redirect
return redirect_class(resolve_url(to, *args, **kwargs))
File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/shortcuts.py", line 130, in resolve_url
return reverse(to, args=args, kwargs=kwargs)
File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/urls/base.py", line 86, in reverse
return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
File "/home/saurav/Documents/programming_Projects/WFI-Community/venv/lib/python3.7/site-packages/django/urls/resolvers.py", line 694, in _reverse_with_prefix
raise NoReverseMatch(msg)
Exception Type: NoReverseMatch at /writeAns/5
Exception Value: Reverse for 'login_page' with keyword arguments '{'args': ['True']}' not found. 1 pattern(s) tried: ['login/$']
The error is
NoReverseMatch at /writeAns/5
Reverse for 'login_page' with keyword arguments '{'args': ['True']}' not found. 1 pattern(s) tried: ['login/$']
For some reason people think the shortcut function redirect would send their user to some other view while passing data to it. This is not true.
According to the documentation the redirect function:
Returns an
HttpResponseRedirect
to the appropriate URL for the arguments passed.
The arguments could be:
A model: the model’s get_absolute_url()
function will be called.
A view name, possibly with arguments: reverse()
will be used to reverse-resolve the name.
An absolute or relative URL, which will be used as-is for the redirect location.
By default issues a temporary redirect; pass permanent=True to
issue a permanent redirect.
What is HttpResponseRedirect? Well it is simply a response with a HTTP 302 status code and a url in the Location header indicating that their requested resource has been temporarily moved to the URL given by the Location header.
Well what if we want to have some data for the user and redirect them somewhere? There are various methods to do that:
Use a GET parameter:
from django.urls import reverse
# While redirecting
return redirect("{}?{}".format(reverse("login_page"), "data=True"))
# At receiving view:
data = request.GET.get("data", False) == "True"
Store something in the session [Django docs] for the user:
# While redirecting
request.session['data'] = "True"
return redirect('login_page')
# At receiving view
data = request.session.get('data') == 'True'
I am trying to make profile pages for each user. I added a code that checks if the user is logged in and does a redirect (see line 12 of the code below).
from django.shortcuts import render
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect, HttpResponse
from .models import Account, ForSale, WTB
from mysite.forms import MyRegistrationForm
def signup(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/user/')
else:
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/user/')
context = {}
context.update(csrf(request))
context['form'] = MyRegistrationForm()
return render(request, 'signup.html', context)
def index(request):
return render(request, 'index.html')
However, upon accessing /signup/ on the site I get the following debug message:
TypeError at /signup/
'bool' object is not callable
Request Method: GET
Request URL: http://url:8000/signup/
Django Version: 2.0
Exception Type: TypeError
Exception Value:
'bool' object is not callable
Exception Location: /www/mysite.com/mysite/views.py in signup, line 13
Python Executable: /usr/bin/python3
Python Version: 3.5.2
Python Path:
['/www/mysite.com',
'/usr/lib/python35.zip',
'/usr/lib/python3.5',
'/usr/lib/python3.5/plat-x86_64-linux-gnu',
'/usr/lib/python3.5/lib-dynload',
'/usr/lib/python3.5/site-packages',
'/usr/local/lib/python3.5/dist-packages',
'/usr/lib/python3/dist-packages']
Server time: Sun, 3 Dec 2017 18:07:54 -0800
In older versions of Django request.user.is_authenticated was a method. It's now an attribute and no longer requires parenthesis. If you change your code to:
if request.user.is_authenticated:
It should be work as expected.
For more info see the docs here: https://docs.djangoproject.com/en/1.11/ref/contrib/auth/#django.contrib.auth.models.User.is_authenticated
you forget to import csrf module please try to add this line and make sure to avoid hardcoded urls try to use url names
from django.core.context_processors import csrf
NameError at /todos/accounts/register/
global name 'csrf' is not defined
Request Method: GET
Request URL: http://localhost:8000/todos/accounts/register/
Django Version: 1.10.5
Exception Type: NameError
Exception Value:
global name 'csrf' is not defined
Exception Location: /home/rahul/Desktop/apps/todolist/todos/views.py in register, line 37
Python Executable: /usr/bin/python
Python Version: 2.7.6
Python Path:
Error in views.py :
from django.shortcuts import render
from django.http import HttpResponse
from .models import Todo
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib.auth.forms import UserCreationForm
#from django.core.context_processors import csrf
def index(request):
todos = Todo.objects.all()[:10]
context = {
'todos' : todos
}
return render(request, 'index.html', context)
def details(request, id):
todo = Todo.objects.get(id=id)
context = {
'todo' : todo
}
return render(request, 'details.html', context)
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register/complete')
else:
form = UserCreationForm()
token = {}
token.update(csrf(request))
token['form'] = form
return render_to_response('registration/registration_form.html', token)
def registration_complete(request):
return render_to_response('registration/registration_complete.html')
Currently my code is showing global name 'csrf' is not defined. To overcome this error, If I uncomment from django.core.context_processors import csrf, than it shows context_processors module not found. Please help.
Thanks in advance.
Django built-in template context processors were moved from package django.core to django.template. So you should change your import as
from django.template.context_processors import csrf
I am new to Django and was trying this code in a tutorial. But now I'm not able to run my program because of the following error:
IndentationError at /
('unexpected indent', ('D:\\django_workspace\\django_bookmarks\\..\\django_bookmarks\\bookmarks\\views.py', 14, 4, ' return HttpResponse(output)\n'))
Request Method: GET
Request URL: http://localhost:8000/
Exception Type: IndentationError
Exception Value:
('unexpected indent', ('D:\\django_workspace\\django_bookmarks\\..\\django_bookmarks\\bookmarks\\views.py', 14, 4, ' return HttpResponse(output)\n'))
Exception Location: D:\django_workspace\django_bookmarks\..\django_bookmarks\urls.py in <module>, line 2
Python Executable: C:\Python26\python.exe
Python Version: 2.6.4
Python Path: ['D:\\django_workspace\\django_bookmarks', 'C:\\Python26', 'C:\\WINDOWS\\system32\\python26.zip', 'C:\\Python26\\DLLs', 'C:\\Python26\\lib', 'C:\\Python26\\lib\\plat-win', 'C:\\Python26\\lib\\lib-tk', 'C:\\Python26\\lib\\site-packages']
Server time: Tue, 9 Mar 2010 19:18:32 +
My views.py file code is:
from django.http import HttpResponse, Http404
from django.contrib.auth.models import User
from django.template import Context
from django.template.loader import get_template
def main_page(request):
template = get_template('main_page.html')
variables = Context({
'head_title': 'Django Bookmarks',
'page_title': 'Welcome to Django Bookmarks',
'page_body': 'Where you can store and share bookmarks!'
})
output = template.render(variables)
return HttpResponse(output)
def user_page(request, username):
try:
user = User.objects.get(username=username)
except:
raise Http404('Requested user not found.')
bookmarks = user.bookmark_set.all()
template = get_template('user_page.html')
variables = Context({
'username': username,
'bookmarks': bookmarks
})
output = template.render(variables)
return HttpResponse(output)
Kindly help me rectify this problem! Thanks in advance.
Most likely you're mixing tabs with spaces - use one or the other for your indenting... preferably spaces, according to this:
http://www.python.org/dev/peps/pep-0008/
First locate the line on which this error occurs. Delete the line entirely. Go to the end of the preceding line and then press enter. Now enter the line.
I am using Django for a project and is already in production.
In the production environment 500.html is rendered whenever a server error occurs.
How do I test the rendering of 500.html in dev environment? Or how do I render 500.html in dev, if I turn-off debug I still get the errors and not 500.html
background: I include some page elements based on a page and some are missing when 500.html is called and want to debug it in dev environment.
I prefer not to turn DEBUG off. Instead I put the following snippet in the urls.py:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^500/$', 'your_custom_view_if_you_wrote_one'),
(r'^404/$', 'django.views.generic.simple.direct_to_template', {'template': '404.html'}),
)
In the snippet above, the error page uses a custom view, you can easily replace it with Django's direct_to_template view though.
Now you can test 500 and 404 pages by calling their urls: http://example.com/500 and http://example.com/404
In Django 1.6 django.views.generic.simple.direct_to_template does not exists anymore, these are my settings for special views:
# urls.py
from django.views.generic import TemplateView
from django.views.defaults import page_not_found, server_error
urlpatterns += [
url(r'^400/$', TemplateView.as_view(template_name='400.html')),
url(r'^403/$', TemplateView.as_view(template_name='403.html')),
url(r'^404/$', page_not_found),
url(r'^500/$', server_error),
]
And if you want to use the default Django 500 view instead of your custom view:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^500/$', 'django.views.defaults.server_error'),
(r'^404/$', 'django.views.generic.simple.direct_to_template', {'template': '404.html'}),
)
Continuing shanyu's answer, in Django 1.3+ use:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^500/$', 'django.views.defaults.server_error'),
(r'^404/$', 'django.views.defaults.page_not_found'),
)
For Django > 3.0, just set the raise_request_exception value to False.
from django.test import TestCase
class ViewTestClass(TestCase):
def test_error_page(self):
self.client.raise_request_exception = False
response = self.client.get(reverse('error-page'))
self.assertEqual(response.status_code, 500)
self.assertTrue(
'some text from the custom 500 page'
in response.content.decode('utf8'))
Documentation: https://docs.djangoproject.com/en/3.2/topics/testing/tools/
NOTE: if the error page raises an exception, that will show up as an ERROR in the test log. You can turn the test logging up to CRITICAL by default to suppress that error.
Are both debug settings false?
settings.DEBUG = False
settings.TEMPLATE_DEBUG = False
How i do and test custom error handlers
Define custom View based on TemplateView
# views.py
from django.views.generic import TemplateView
class ErrorHandler(TemplateView):
""" Render error template """
error_code = 404
template_name = 'index/error.html'
def dispatch(self, request, *args, **kwargs):
""" For error on any methods return just GET """
return self.get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['error_code'] = self.error_code
return context
def render_to_response(self, context, **response_kwargs):
""" Return correct status code """
response_kwargs = response_kwargs or {}
response_kwargs.update(status=self.error_code)
return super().render_to_response(context, **response_kwargs)
Tell django to use custom error handlers
# urls.py
from index.views import ErrorHandler
# error handing handlers - fly binding
for code in (400, 403, 404, 500):
vars()['handler{}'.format(code)] = ErrorHandler.as_view(error_code=code)
Testcase for custom error handlers
# tests.py
from unittest import mock
from django.test import TestCase
from django.core.exceptions import SuspiciousOperation, PermissionDenied
from django.http import Http404
from index import views
class ErrorHandlersTestCase(TestCase):
""" Check is correct error handlers work """
def raise_(exception):
def wrapped(*args, **kwargs):
raise exception('Test exception')
return wrapped
def test_index_page(self):
""" Should check is 200 on index page """
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'index/index.html')
#mock.patch('index.views.IndexView.get', raise_(Http404))
def test_404_page(self):
""" Should check is 404 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 404)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('404 Page not found', response.content.decode('utf-8'))
#mock.patch('index.views.IndexView.get', views.ErrorHandler.as_view(error_code=500))
def test_500_page(self):
""" Should check is 500 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 500)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('500 Server Error', response.content.decode('utf-8'))
#mock.patch('index.views.IndexView.get', raise_(SuspiciousOperation))
def test_400_page(self):
""" Should check is 400 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 400)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('400 Bad request', response.content.decode('utf-8'))
#mock.patch('index.views.IndexView.get', raise_(PermissionDenied))
def test_403_page(self):
""" Should check is 403 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 403)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('403 Permission Denied', response.content.decode('utf-8'))
urls.py
handler500 = 'project.apps.core.views.handler500'
handler404 = 'project.apps.core.views.handler404'
views.py
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponseServerError, HttpResponseNotFound
def handler500(request, template_name='500.html'):
t = get_template(template_name)
ctx = Context({})
return HttpResponseServerError(t.render(ctx))
def handler404(request, template_name='404.html'):
t = get_template(template_name)
ctx = Context({})
return HttpResponseNotFound(t.render(ctx))
tests.py
from django.test import TestCase
from django.test.client import RequestFactory
from project import urls
from ..views import handler404, handler500
class TestErrorPages(TestCase):
def test_error_handlers(self):
self.assertTrue(urls.handler404.endswith('.handler404'))
self.assertTrue(urls.handler500.endswith('.handler500'))
factory = RequestFactory()
request = factory.get('/')
response = handler404(request)
self.assertEqual(response.status_code, 404)
self.assertIn('404 Not Found!!', unicode(response))
response = handler500(request)
self.assertEqual(response.status_code, 500)
self.assertIn('500 Internal Server Error', unicode(response))
Update for Django > 1.6 and without getting
page_not_found() missing 1 required positional argument: 'exception'
Inspired by this answer:
# urls.py
from django.views.defaults import page_not_found, server_error, permission_denied, bad_request
[...]
if settings.DEBUG:
# This allows the error pages to be debugged during development, just visit
# these url in browser to see how these error pages look like.
urlpatterns += [
path('400/', bad_request, kwargs={'exception': Exception('Bad Request!')}),
path('403/', permission_denied, kwargs={'exception': Exception('Permission Denied')}),
path('404/', page_not_found, kwargs={'exception': Exception('Page not Found')}),
path('500/', server_error),
You can simply define the handler404 and handler500 for errors in your main views.py file as detailed in this answer:
https://stackoverflow.com/a/18009660/1913888
This will return the error that you desire when Django routes to that handler. No custom URL configuration is needed to route to a different URL name.
In Django versions < 3.0, you should do as follows:
client.py
from django.core.signals import got_request_exception
from django.template import TemplateDoesNotExist
from django.test import signals
from django.test.client import Client as DjangoClient, store_rendered_templates
from django.urls import resolve
from django.utils import six
from django.utils.functional import SimpleLazyObject, curry
class Client(DjangoClient):
"""Test client that does not raise Exceptions if requested."""
def __init__(self,
enforce_csrf_checks=False,
raise_request_exception=True, **defaults):
super(Client, self).__init__(enforce_csrf_checks=enforce_csrf_checks,
**defaults)
self.raise_request_exception = raise_request_exception
def request(self, **request):
"""
The master request method. Composes the environment dictionary
and passes to the handler, returning the result of the handler.
Assumes defaults for the query environment, which can be overridden
using the arguments to the request.
"""
environ = self._base_environ(**request)
# Curry a data dictionary into an instance of the template renderer
# callback function.
data = {}
on_template_render = curry(store_rendered_templates, data)
signal_uid = "template-render-%s" % id(request)
signals.template_rendered.connect(on_template_render,
dispatch_uid=signal_uid)
# Capture exceptions created by the handler.
exception_uid = "request-exception-%s" % id(request)
got_request_exception.connect(self.store_exc_info,
dispatch_uid=exception_uid)
try:
try:
response = self.handler(environ)
except TemplateDoesNotExist as e:
# If the view raises an exception, Django will attempt to show
# the 500.html template. If that template is not available,
# we should ignore the error in favor of re-raising the
# underlying exception that caused the 500 error. Any other
# template found to be missing during view error handling
# should be reported as-is.
if e.args != ('500.html',):
raise
# Look for a signalled exception, clear the current context
# exception data, then re-raise the signalled exception.
# Also make sure that the signalled exception is cleared from
# the local cache!
response.exc_info = self.exc_info # Patch exception handling
if self.exc_info:
exc_info = self.exc_info
self.exc_info = None
if self.raise_request_exception: # Patch exception handling
six.reraise(*exc_info)
# Save the client and request that stimulated the response.
response.client = self
response.request = request
# Add any rendered template detail to the response.
response.templates = data.get("templates", [])
response.context = data.get("context")
response.json = curry(self._parse_json, response)
# Attach the ResolverMatch instance to the response
response.resolver_match = SimpleLazyObject(
lambda: resolve(request['PATH_INFO'])
)
# Flatten a single context. Not really necessary anymore thanks to
# the __getattr__ flattening in ContextList, but has some edge-case
# backwards-compatibility implications.
if response.context and len(response.context) == 1:
response.context = response.context[0]
# Update persistent cookie data.
if response.cookies:
self.cookies.update(response.cookies)
return response
finally:
signals.template_rendered.disconnect(dispatch_uid=signal_uid)
got_request_exception.disconnect(dispatch_uid=exception_uid)
tests.py
from unittest import mock
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from django.test import TestCase, override_settings
from .client import Client # Important, we use our own Client here!
class TestErrors(TestCase):
"""Test errors."""
#classmethod
def setUpClass(cls):
super(TestErrors, cls).setUpClass()
cls.username = 'admin'
cls.email = 'admin#localhost'
cls.password = 'test1234test1234'
cls.not_found_url = '/i-do-not-exist/'
cls.internal_server_error_url = reverse('password_reset')
def setUp(self):
super(TestErrors, self).setUp()
User = get_user_model()
User.objects.create_user(
self.username,
self.email,
self.password,
is_staff=True,
is_active=True
)
self.client = Client(raise_request_exception=False)
# Mock in order to trigger Exception and resulting Internal server error
#mock.patch('django.contrib.auth.views.PasswordResetView.form_class', None)
#override_settings(DEBUG=False)
def test_errors(self):
self.client.login(username=self.username, password=self.password)
with self.subTest("Not found (404)"):
response = self.client.get(self.not_found_url, follow=True)
self.assertNotIn('^admin/', str(response.content))
with self.subTest("Internal server error (500)"):
response = self.client.get(self.internal_server_error_url,
follow=True)
self.assertNotIn('TypeError', str(response.content))
Starting from Django 3.0 you could skip the custom Client definition and just use the code from tests.py.