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