Unable to provide a template for error 403 - python

Well, at this moment I know how to make a custom error 404 page (and it actually works in my app). I followed the same strategy step by step to make a 403 page, but to no avail. So, this is what I have done:
#root urls.py
handler403 = 'blog.views.custom_403'
#blog views.py
def custom_403(request):
template = loader.get_template('blog/403.html')
context = RequestContext(request,{})
return HttpResponse(template.render(context))
Then, in one of my functions I have this code:
return HttpResponseForbidden()
I thought, it would render 403.html, but what I see is just a message 403 FORBIDDEN in the console.

The trouble is, you are not raising a 403 exception (as you did for the 404), but simply returning a response with a status code of 403. As the docs show, you need to raise django.views.defaults.permission_denied to trigger the 403 page.
from django.core.exceptions import PermissionDenied
...
raise PermissionDenied

Related

Django how to send a argument in handler404?

How can I override handler404 to pass arguments into a view?
I need to pass the arguments text and error
# views.py
def handler404(request, error, text):
response = render_to_response('error/40X.html', {'error': error, 'text':text})
response.status_code = error
return response
The 404 handler code in urls.py is:
handler404 = 'app.views.handler404'
I am using Django v1.10 and Python v3.5, and would prefer avoiding having to create a function for each error.
The question was translated, and I would be grateful for corrections, original
I don't think you need a custom handler404 view here. Django's page_not_found view does what you want.
In Django 1.9+, you can include {{ exception }} in the 404 template.
In your view, you could set the message when raising the exception, for example:
from django.http import Http404
def my_view(request):
raise Http404('custom error message')
It doesn't make sense to set response.status_code in the handler - if it's handler404, then the status code should always be 404.

How does HttpResponse(status=<code>) work in django?

I'm experimenting with HTTP error codes in django so I have a question about HttpResponse(status=<code>). For example, I want to send a HTTP error code 405, I have the following code:
def myview(request):
if request.method == 'POST':
...
else:
return HttpResponse(status=405)
Also I have my template for this HTTP error code (405.html) and I put the following code line in urls.py
handler405 = 'handling_error.views.bad_method'
And my bad_method view is the following:
def bad_method(request):
datos_template = {}
return render(request, '405.html', datos_template, status=405)
I thought in this way Django redirect to correct template according to the HTTP error code, but it doesn't work, then:
Have I done incorrect something?
How does HttpResponse(status=) work in django?
What is the goal of sending a HTTP error code through HttpResponse(status=)?
Sorry, many questions :P
I hope someone can help me.
HttpResponse(status=[code]) is just a way of sending the actual HTTP status code in the header of the response. It arrives at the client with that status_code, but does not do any changing of the data except for the HTTP header. You can pass any status code with a properly-working response, and it will still show up as before, but if you go into the browser's console you will see that it read it as a "405" page.
HTTP headers are simply transferred with each request and response for web server parsing and providing metadata/info to developers. Even 404 pages have content sent with them, to tell the user that there was a 404; if it didn't, the user would just get a blank page and have no idea what went wrong.
If you want to signify an error, you can take a look at these docs. Alternatively, you can use the HttpResponseRedirect (see here) option to direct to an error-view that serves a custom error response.
Django lets you specify error handlers for handler400, handler403, handler404 and handler500 in your urls.py. It does not support a handler405.
Note that you can return http responses with any status, and Django will return that response to the user, it won't call the handler for that status code.
The error handlers are called when an exception is raised. For example, if Http404 is raised in a view, Django will call the handler404 view.

How to retain stacktrace when you must return a value?

For a web app, I have a method get_stuff_for_payment that raises PermissionDenied for which Django generates a HTTP 403 to the user.
I am now asked to show a friendly error page instead of the generic 403. The following code does it. But how do I retain the stacktrace when I do this?
try:
stuff = get_stuff_for_payment(id)
except PermissionDenied:
return render(request, 'friendly_error_page.html', context)
If you want just to log it, then do so. The logging.exception method will log a message and append a traceback automatically:
except PermissionDenied as err:
logger.exception('Permission was denied: %s', err)
StackTrace of Errors on our custom Template in python
except PermissionDenied:
return render(request, 'friendly_error_page.html', context)
is not a good way in django gor dealing with 403 , 4xx or 5xx errors.
If we want to show exceptions which are generated , on ur template(403.html) then we could write your own 403 view, grabbing the exception and passing it to your 403 template.
Steps:
#.In views.py:
import sys,traceback
def custom_403(request):
t = loader.get_template('403.html')
logger.info("custom msg",sys.exc_info()) // for traceback
type, value, tb = sys.exc_info()
return HttpResponseServerError(t.render(Context({
'exception_value': value,
'value':type,
'tb':traceback.format_exception(type, value,
tb)
},RequestContext(request))))
#.In Main Urls.py:
from django.conf.urls.defaults import *
handler403 = 'Project.web.services.views.custom_403'
and if you want to show stacktrace to user use this template otherwise your custom template
#.In Template(403.html):
{{ exception_value }}{{value}}{{tb}}

Django REST Custom Errors

I’m trying to create a custom error response from the REST Django framework.
I’ve included the following in my views.py,
from rest_framework.views import exception_handler
def custom_exception_handler(exc):
"""
Custom exception handler for Django Rest Framework that adds
the `status_code` to the response and renames the `detail` key to `error`.
"""
response = exception_handler(exc)
if response is not None:
response.data['status_code'] = response.status_code
response.data['error'] = response.data['detail']
response.data['detail'] = "CUSTOM ERROR"
return response
And also added the following to settings.py.
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
'EXCEPTION_HANDLER': 'project.input.utils.custom_exception_handler'
}
Am I missing something as I don’t get the expected response. i.e a custom error message in the 400 API response.
Thanks,
As Bibhas said, with custom exception handlers, you only can return own defined errors when an exception is called. If you want to return a custom response error without exceptions being triggered, you need to return it in the view itself. For example:
return Response({'detail' : "Invalid arguments", 'args' : ['arg1', 'arg2']},
status = status.HTTP_400_BAD_REQUEST)
From the documentation -
Note that the exception handler will only be called for responses generated by raised exceptions. It will not be used for any responses returned directly by the view, such as the HTTP_400_BAD_REQUEST responses that are returned by the generic views when serializer validation fails.

Django: send error to admin and return response to user

I have got JSON API (as the part of the project) implemented with Django.
Sometimes I return error to user in JSON form. I want to notify admin via standard error reporting procedure via email (for example when uncaught exception raised). But I want to return some JSON response too, not 500 error page.
Some metacode to make sure that everything clear:
def request_handler(request):
try:
code_that_rises_an_exception()
return response('{"result":"success"}')
except Exception,e:
notify_admin_about_error(e) # <- this function is required
return response('{"result":"error"}')
Thank you!
You can use Django Middleware for this. Middlewares allow you to modify/process Django's HttpRequest object that is supplied to a view and HttpResponse object that is returned by a view as well as take action when a view raises an exception. You can do variety of tasks with this such as logging of the meta data of the requests you receive, error reporting etc. Django calls process_exception whenever an exception is raised by a view and you can define process_exception() to send a mail to you whenever an exception gets raised.
class ErrorReportingMiddleware(object):
def process_exception(self, request, exception):
send_mail_to_admin(exception) # you can collect some more information here
return HttpResponse('{"result":"error"}') # this response is returned to the user
Add this class to your MIDDLEWARE_CLASSES variable in settings.py at the end of that tuple.
Your view would reduce to:
def request_handler(request):
code_that_rises_an_exception()
return response('{"result":"success"}')
Now if an exception is raised by request_handler, Django would call process_exception method of your ErrorReportingMiddleware which will send a mail to the admin about the exception and return a JSON response to the browser instead of a 500 page. I would implement send_mail_to_admin as an asynchronous function so that the processing of the response by django doesn't get blocked due to sending of mail and quick response is returned to the user.

Categories

Resources