225

I'd like to do the following:

raise HttpResponseForbidden()

But I get the error:

exceptions must be old-style classes or derived from BaseException, not HttpResponseForbidden

How should I do this?

Vini.g.fer
  • 11,639
  • 16
  • 61
  • 90
tallowen
  • 4,198
  • 7
  • 27
  • 35

4 Answers4

464

if you want to raise an exception you can use:

from django.core.exceptions import PermissionDenied

def your_view(...):
    raise PermissionDenied()

It is documented here :

https://docs.djangoproject.com/en/stable/ref/views/#the-403-http-forbidden-view

As opposed to returing HttpResponseForbidden, raising PermissionDenied causes the error to be rendered using the 403.html template, or you can use middleware to show a custom "Forbidden" view.

andyhasit
  • 14,137
  • 7
  • 49
  • 51
Chris
  • 12,192
  • 5
  • 21
  • 23
  • You can still provide middleware with a process_exception method and render your view from there. – deterb May 08 '14 at 19:32
  • 2
    Can we add a custom message in PermissionDenied? – A.J. Aug 19 '14 at 05:59
  • 2
    Jack, yes you can -- do something like: raise PermissionDenied("No logged in user") – Mark Chackerian Oct 08 '14 at 13:43
  • 2
    Not sure if it matters, but the docs say `throw PermissionDenied` not as a function call, without the `()` at the end. – Fydo Nov 14 '14 at 15:05
  • 2
    What's the advantage of using this over HttpResponseForbidden? – Flimm Jan 06 '16 at 16:41
  • 3
    @Flimm: This automatically triggers 403 at middleware level, allowing you to show your custom "Forbidden" view. – Damaged Organic Mar 08 '16 at 15:03
  • 1
    @MarkChackerian any idea of `PermissionDenied` in Django 1.6. I created a custom 403.html . How to retrieve the custom message in html ? . `raise PermissionDenied("custom message")` dont show my custom message – Manuj Rastogi Jan 06 '17 at 12:07
  • Using this in an admin view and still getting 500 instead of 403. Any idea what I could be doing wrong? – Ariel Jan 30 '19 at 11:00
217

Return it from the view as you would any other response.

from django.http import HttpResponseForbidden

return HttpResponseForbidden()
Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 45
    Why does there exists an exception class `Http404` but not `Http403`? Why the inconsistency? – Flimm Jan 28 '16 at 13:34
  • 1
    @Flimm http://stackoverflow.com/questions/3297048/403-forbidden-vs-401-unauthorized-http-responses I'm not sure about Django, but Django REST Framework has: from rest_framework import status status.HTTP_403_FORBIDDEN 403 – David Watson Mar 04 '16 at 18:35
  • 26
    Actually using `raise PermissionDenied` has the advantage of letting you show your custom 403 view – gdvalderrama Jul 08 '16 at 09:01
  • I think that the question asks for a very specific thing and this answer does not answer that specific thing, but show another approach. See the answer below, which answers the very specific question - and IMO it should be the accepted answer. – babis21 Jul 07 '22 at 09:45
13

You can optionally supply a custom template named "403.html" to control the rendering of 403 HTTP errors.

As correctly pointed out by @dave-halter, The 403 template can only be used if you raise PermissionDenied

Below is a sample view used to test custom templates "403.html", "404.html" and "500.html"; please make sure to set DEBUG=False in project's settings or the framework will show a traceback instead for 404 and 500.

from django.http import HttpResponse
from django.http import Http404
from django.core.exceptions import PermissionDenied


def index(request):

    html = """
<!DOCTYPE html>
<html lang="en">
  <body>
    <ul>
        <li><a href="/">home</a></li>
        <li><a href="?action=raise403">Raise Error 403</a></li>
        <li><a href="?action=raise404">Raise Error 404</a></li>
        <li><a href="?action=raise500">Raise Error 500</a></li>
    </ul>
  </body>
</html>
"""

    action = request.GET.get('action', '')
    if action == 'raise403':
        raise PermissionDenied
    elif action == 'raise404':
        raise Http404
    elif action == 'raise500':
        raise Exception('Server error')

    return HttpResponse(html)
Mario Orlandi
  • 5,629
  • 26
  • 29
5

Try this Way , sending message with Error

from django.core.exceptions import PermissionDenied
raise PermissionDenied("You do not have permission to Enter Clients in Other Company, Be Careful")
Saad Mirza
  • 1,154
  • 14
  • 22