'Redirect anonymous users to log in (don't show them anything)
Django 1.9.6.
I want to absolutely disable the whole website from viewing by anonymous users. Anonymous users will always be redirected to login page.
I have created a general view. The problem is that subclasses of GeneralView may not just render a template but perform some calculations or just be of different kinds: DetailView, ListView etc.
class GeneralView(View):
def get(self, request, template):
if not request.user.is_authenticated() and request.user.is_active:
return redirect("auth_login")
else:
return render(request, template)
If I try to inherit, the code gets clumsy:
class HomePageView(GeneralView):
def get(self, request, template):
super().get(self, request)
Well, what can I do here? I get error message that my get method doesn't return HttpResponse.
I can rewrite get method of the superclass to return status code. Then check it in the subclass. But this seems to be garbage.
In other words I'm lost in clouds of inheritance. Could you give me a kick here how always to redirect anonymous users to login page, whereas let logged in users see everything.
Thank you in advance.
Solution 1:[1]
You could use the UserPassesTestMixin for this.
from django.core.urlresolvers import reverse_lazy
class GeneralView(UserPassesTestMixin, View):
def test_func(self):
# I assume you missed out the brackets in your question and actually wanted 'if not (request.user.is_authenticated() and request.user.is_active)'
return request.user.is_authenticated() and request.user.is_active
login_url = reverse_lazy('auth_login')
The mixin overrides dispatch, so you won't have to call super() when you override get() in your view.
class HomePageView(GeneralView):
def get(self, request):
...
Solution 2:[2]
I think your error for get method not returning belongs to not putting a return statement. in fact, in get method of the child class you should do:
class HomePageView(GeneralView):
def get(self, request, template):
return super().get(self, request)
That should solve the error
Solution 3:[3]
If you have lots of views and you do not want to touch any one you can just use Middleware for this issue. Try code below:
import traceback
from django.contrib.auth.decorators import login_required
class RejectAnonymousUsersMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
current_route_name = resolve(request.path_info).url_name
if current_route_name in settings.AUTH_EXEMPT_ROUTES:
return
if request.user.is_authenticated:
return
return login_required(view_func)(request, *view_args, **view_kwargs)
Cautions:
- You must add this middleware to the bottommost of middleware section of settings.py
- You should put this variable in settings.py
- AUTH_EXEMPT_ROUTES = ('register', 'login', 'forgot-password')
Solution 4:[4]
New versions of Django provides the @login_required decorator. If an anonymous user tries to access the view, the system redirects to the login page.
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
It can be used in function views, as shown above, or generic views (using @method_decorator, usually in dispatch method)
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import TemplateView
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alasdair |
| Solution 2 | Nikign |
| Solution 3 | |
| Solution 4 | William |
