How can I redirect a user to the login page when confronted with a 403 Forbidden?
Consider the following code:
urls.py
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
urlpatterns = patterns('',
url(r'^', include(router.urls)),
)
views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
renderer_classes = (renderers.JSONRenderer, renderers.TemplateHTMLRenderer)
template_name='rest_framework/users.html'
def list(self, request, *args, **kwargs):
response = super(viewSet, self).list(request, *args, **kwargs)
if request.accepted_renderer.format == 'html':
return Response({'request':request, 'queryset': response.data['results']})
return response
If I visit /domain/users while not logged in, I'll get a 403 Forbidden error. I would like to instead, redirect to the login page. In other words, never show 403 errors but instead redirect directly to the login page.
I have tried putting:
@login_required
def list(...):
but that does not work. I assume because its inside a viewset.
I have also tried:
def list(...):
if not request.user.is_authenticated():
return render_to_response('domain/login.html')
but again, doesn't work.
I tried various 403middlewares but to no avail.
I tried redirecting via the handler403 handler in urls.py
handler403 = 'site.views.login'
No success.
What to do?
Django version: 1.5.4
You can't use the standard login_required decorator on a class method. You have to either wrap the as_view() when you use it in the URL:
url(r'...', login_required(UserViewSet.as_view()))
or wrap the decorator with django.utils.decorators.method_decorator and apply it to the class dispatch method:
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
class UserViewSet(viewsets.ModelViewSet):
...
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
....
(see https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/#decorating-class-based-views)
For class-based views you can incorporate this into a reusable PermissionRequiredMixin - see https://stackoverflow.com/a/6455140/839875
Alternatively you can raise a django.core.exceptions.PermissionDenied exception which Django will catch with django.views.defaults.permission_denied
(see https://docs.djangoproject.com/en/1.5/topics/http/views/#the-403-http-forbidden-view)
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