Django, redirect all non-authenticated users to landing page
Question:
I have a django website with many urls and views. Now I have asked to redirect all non-authenticated users to a certain landing page. So, all views must check if user.is_authenticated()
and return to a new set of landing pages.
Can it be done in a pretty way, instead of messing with my views.py
/urls.py
that much?
Answers:
see the docs for login required decorator
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
another option is to add it to your urls.py patterns, see this answer
urlpatterns = patterns('',
(r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
)
You can use Middleware.
Something like this will check user auth every request:
class AuthRequiredMiddleware(object):
def process_request(self, request):
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('landing_page')) # or http response
return None
Docs: process_request
Also, don’t forget to enable it in settings.py
MIDDLEWARE_CLASSES = (
...
'path.to.your.AuthRequiredMiddleware',
)
This can be done with middleware.
I’ve found a really nifty djangosnippet that does exactly what you are asking for. You can find it here, and it looks like:
from django.http import HttpResponseRedirect
from django.conf import settings
from re import compile
EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
"""
Middleware that requires a user to be authenticated to view any page other
than LOGIN_URL. Exemptions to this requirement can optionally be specified
in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
you can copy from your urls.py).
Requires authentication middleware and template context processors to be
loaded. You'll get an error if they aren't.
"""
def process_request(self, request):
assert hasattr(request, 'user'), "The Login Required middleware
requires authentication middleware to be installed. Edit your
MIDDLEWARE_CLASSES setting to insert
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)
All you have to do is to save the file as middleware.py
and include the class in you’re settings.py, i.e.
MIDDLEWARE_CLASSES += ('projectname.common.middleware.RequireLoginMiddleware',)
You can also define a LOGIN_URL
in settings.py
, so that you’ll be redirected to your custom login page. The default LOGIN_URL
is '/accounts/login/'
.
As of Django 1.10, the custom middleware classes must implement the new style syntax. You can use the following class to verify that the user is logged in while trying to access any views.
from django.shortcuts import HttpResponseRedirect
class AuthRequiredMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
if not request.user.is_authenticated: # in Django > 3 this is a boolean
return HttpResponseRedirect('login')
# Code to be executed for each request/response after
# the view is called.
return response
There is a simpler way to do this, just add the “login_url” parameter to @login_required and if the user is not login he will be redirected to the login page. You can find it here
from django.contrib.auth.decorators import login_required
@login_required(login_url='/accounts/login/')
def my_view(request):
...
Maybe too late but in django 1.9+ it’s too easy.
Django introduced Login Required mixin for generic classes and this a great example
here by William S. Vincent
simply in your view add LoginRequiredMixin as parent class
from django.contrib.auth.mixins import LoginRequiredMixin
class BlogUpdateView(LoginRequiredMixin, UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']
Also you can use login_required decorator for method request
from django.contrib.auth.decorators import login_required
@login_required(login_url='/login/')
def home(request):
return render(request, "home.html")
It’s showing like this: http://127.0.0.1:1235/login/?next=/home/
You can avoid specifying login_url
by setting LOGIN_URL
.
Therefore, in settings.py
add:
LOGIN_URL = '<some_url>'
And in your views.py
annotate relevant functions with only @login_required
:
@login_required
def some_view_function(request):
If you need to redirect within a view function, you can do so with:
return redirect_to_login(request.get_full_path())
I’m using class based views and I couldn’t get any of these solutions to work for what I needed so I’ll post my working solution here.
class ManagementPageView(TemplateView):
# Make a dispatch method to handle authentication
def dispatch(self, *args, **kwargs):
# Check if user is authenticated
if not self.request.user.is_authenticated:
# Redirect them to the home page if not
return redirect('home')
# Render the template if they are
return render(self.request, 'management.html')
I have a django website with many urls and views. Now I have asked to redirect all non-authenticated users to a certain landing page. So, all views must check if user.is_authenticated()
and return to a new set of landing pages.
Can it be done in a pretty way, instead of messing with my views.py
/urls.py
that much?
see the docs for login required decorator
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
another option is to add it to your urls.py patterns, see this answer
urlpatterns = patterns('',
(r'^foo/$', login_required(direct_to_template), {'template': 'foo_index.html'}),
)
You can use Middleware.
Something like this will check user auth every request:
class AuthRequiredMiddleware(object):
def process_request(self, request):
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('landing_page')) # or http response
return None
Docs: process_request
Also, don’t forget to enable it in settings.py
MIDDLEWARE_CLASSES = (
...
'path.to.your.AuthRequiredMiddleware',
)
This can be done with middleware.
I’ve found a really nifty djangosnippet that does exactly what you are asking for. You can find it here, and it looks like:
from django.http import HttpResponseRedirect
from django.conf import settings
from re import compile
EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
"""
Middleware that requires a user to be authenticated to view any page other
than LOGIN_URL. Exemptions to this requirement can optionally be specified
in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which
you can copy from your urls.py).
Requires authentication middleware and template context processors to be
loaded. You'll get an error if they aren't.
"""
def process_request(self, request):
assert hasattr(request, 'user'), "The Login Required middleware
requires authentication middleware to be installed. Edit your
MIDDLEWARE_CLASSES setting to insert
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)
All you have to do is to save the file as middleware.py
and include the class in you’re settings.py, i.e.
MIDDLEWARE_CLASSES += ('projectname.common.middleware.RequireLoginMiddleware',)
You can also define a LOGIN_URL
in settings.py
, so that you’ll be redirected to your custom login page. The default LOGIN_URL
is '/accounts/login/'
.
As of Django 1.10, the custom middleware classes must implement the new style syntax. You can use the following class to verify that the user is logged in while trying to access any views.
from django.shortcuts import HttpResponseRedirect
class AuthRequiredMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
if not request.user.is_authenticated: # in Django > 3 this is a boolean
return HttpResponseRedirect('login')
# Code to be executed for each request/response after
# the view is called.
return response
There is a simpler way to do this, just add the “login_url” parameter to @login_required and if the user is not login he will be redirected to the login page. You can find it here
from django.contrib.auth.decorators import login_required
@login_required(login_url='/accounts/login/')
def my_view(request):
...
Maybe too late but in django 1.9+ it’s too easy.
Django introduced Login Required mixin for generic classes and this a great example
here by William S. Vincent
simply in your view add LoginRequiredMixin as parent class
from django.contrib.auth.mixins import LoginRequiredMixin
class BlogUpdateView(LoginRequiredMixin, UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body']
Also you can use login_required decorator for method request
from django.contrib.auth.decorators import login_required
@login_required(login_url='/login/')
def home(request):
return render(request, "home.html")
It’s showing like this: http://127.0.0.1:1235/login/?next=/home/
You can avoid specifying login_url
by setting LOGIN_URL
.
Therefore, in settings.py
add:
LOGIN_URL = '<some_url>'
And in your views.py
annotate relevant functions with only @login_required
:
@login_required
def some_view_function(request):
If you need to redirect within a view function, you can do so with:
return redirect_to_login(request.get_full_path())
I’m using class based views and I couldn’t get any of these solutions to work for what I needed so I’ll post my working solution here.
class ManagementPageView(TemplateView):
# Make a dispatch method to handle authentication
def dispatch(self, *args, **kwargs):
# Check if user is authenticated
if not self.request.user.is_authenticated:
# Redirect them to the home page if not
return redirect('home')
# Render the template if they are
return render(self.request, 'management.html')