Mohammed Farahmand
Mohammed Farahmand

Reputation: 498

Restricting all the views to authenticated users in Django

I'm new to Django and I'm working on a project which has a login page as its index and a signup page. The rest of the pages all must be restricted to logged in users and if an unauthenticated user attempts to reach them, he/she must be redirected to the login page.

I see that @login_required decorator would make a single view restricted to logged in users but is there a better way to make all the views restricted and only a few available to unauthenticated users?

Upvotes: 15

Views: 9977

Answers (3)

someone
someone

Reputation: 479

In Django 5.1 you can use the LoginRequiredMiddleware. From the docs (2024/11/11):

Redirects all unauthenticated requests to a login page, except for views excluded with login_not_required(). The login page defaults to settings.LOGIN_URL, but can be customized.

Enable this middleware by adding it to the MIDDLEWARE setting after AuthenticationMiddleware:

MIDDLEWARE = [
    "...",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.auth.middleware.LoginRequiredMiddleware",
    "...",
]

Make a view public, allowing unauthenticated requests, with login_not_required(). For example:

from django.contrib.auth.decorators import login_not_required


@login_not_required
def contact_us(request): ...

Upvotes: 1

wim
wim

Reputation: 362478

...is there a better way to make all the views restricted and only a few available to unauthenticated users?

This is a good use-case for class based views. Define a base class with the login handling, say LoginRequiredView, and make any authenticated endpoints subclass this base, rather than using function-based views with decoration on each function.

The few views available to unauthenticated users will inherit from Django's generic View rather than the login required base.

Django actually provides a mixin class which you can use:

from django.contrib.auth.mixins import LoginRequiredMixin

class LoginRequiredView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

When a view uses this mixin, or subclasses a base with the mixin, requests by non-authenticated users will be redirected to the login page.

Upvotes: 2

Blender
Blender

Reputation: 298056

You can write a middleware:

from django.contrib.auth.decorators import login_required

def login_exempt(view):
    view.login_exempt = True
    return view


class LoginRequiredMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_view(self, request, view_func, view_args, view_kwargs):
        if getattr(view_func, 'login_exempt', False):
            return

        if request.user.is_authenticated:
            return

        # You probably want to exclude the login/logout views, etc.

        return login_required(view_func)(request, *view_args, **view_kwargs)

You add the middleware to your MIDDLEWARES list and decorate the views you don't want authenticated with login_exempt.

Upvotes: 22

Related Questions