I have internal account privacy permissions in my project(e.g. only friends can see profile page of user) and I want to have custom permission denied page for this case. Is there any way to return response from TemplateView with status code equals 403?
Something like this:
class PrivacyDeniedView(TempateView):
template_name = '...'
status_code = 403
I can do this by override dispatch() but maybe Django has out of the box solution
Answer: it looks like there no generic solution. The best way is proposed by @alecxe, but encapsulated in Mixin as @FoxMaSk proposed
One option is to override get() method of your TemplateView
class:
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
return self.render_to_response(context, status=403)
You can subclass TemplateResponse
and set response_class
in the view. For example:
from django.template.response import TemplateResponse
class TemplateResponseForbidden(TemplateResponse):
status_code = 403
class PrivacyDeniedView(TemplateView):
response_class = TemplateResponseForbidden
...
This approach is more DRY than the other suggestions because you don't need to copy and paste any code from TemplateView
(e.g. the call to render_to_string()
).
I tested this in Django 1.6.
While alecxe's answer works, I strongly suggest you to avoid overriding get
; it's easy to forget that CBV's can have other methods like post
, and if you're overriding one you should do the same for the others.
In fact, there is no need to create a separate view just to display a 403 error; Django already has django.http.HttpResponseForbidden
. So instead of redirecting to your view, just do something along the lines of:
if not user.has_permission(): # or however you check the permission
return HttpResponseForbidden()
Or, if you want to render a particular template:
if not user.has_permission(): # or however you check the permission
return HttpResponseForbidden(loader.render_to_string("403.html"))
I just encountered this problem as well. My goal was to be able to specify the status code in urls.py, e.g.:
url(r'^login/error/?$', TemplateView.as_view(template_name='auth/login_error.html', status=503), name='login_error'),
So using the previous answers in this thread as idea starters, I came up with the following solution:
class TemplateView(django.views.generic.TemplateView):
status = 200
def render_to_response(self, context, **response_kwargs):
response_kwargs['status'] = self.status
return super(TemplateView, self).render_to_response(context, **response_kwargs)
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