[Django]-Set all pages to require login, globally?

11👍

from django.shortcuts import redirect
from django.conf import settings


class LoginRequiredMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.login_url = settings.LOGIN_URL
        self.open_urls = [self.login_url] + \
                         getattr(settings, 'OPEN_URLS', [])

    def __call__(self, request):
        if not request.user.is_authenticated \
        and not request.path_info in self.open_urls:
            return redirect(self.login_url+'?next='+request.path)

        return self.get_response(request)

4👍

The way I solved this, was to have mixin class, with the decorator (or whatever code you need). Although you have to remember to call the super(Class, self).get(...) function, so I guess it’s not so different after all.

On the other hand, having a set of mixins that does different things I found was quite good at getting a very simple view to do a lot without much code.

Edit

This is how I did in my last project:

class BaseAuthMixin(object):
    def auth_check(self, user):
        return True

    def dispatch(self, request, *args, **kwargs):
        if not self.auth_check(request.user):
            from django.http import HttpResponseRedirect
            from django.contrib.auth import logout

            is_web = False
            is_live = False

            if hasattr(self, 'get_url_name'):
                from django.core.urlresolvers import reverse
                from django.core.urlresolvers import NoReverseMatch

                try:
                    next = reverse(self.get_url_name(), kwargs=kwargs)
                except NoReverseMatch:
                    next = ''
                else:
                    next= '?next=' + next

            logout(request)

            redirect_url = settings.LOGIN_URL
            redirect_url += next

            return HttpResponseRedirect(redirect_url)
        else:
            return super(BaseAuthMixin, self).dispatch(request, *args, **kwargs)

class LoginRequiredMixin(BaseAuthMixin):
    """
    Check if the view needs the user to be logged in.
    """
    def auth_check(self, user):
        if not super(LoginRequiredMixin, self).auth_check(user):
            return False
        else:
            if hasattr(self, 'login_required'):
                if self.login_required and not user.is_authenticated():
                    return False
        return True

class MyDefaultMixin(LoginRequiredMixin):
    """
    Mixin that inherits from all common view mixins.
    """
    pass

The above is then used by the view-classes (I used Django 1.3 with class-based views):

from django.views.generic import TemplateView

class SomeViewClass(TemplateView, MyDefaultMixin):
    # Used by 'LoginRequiredMixin' to check if a user has to be logged in
    login_required = True

    # Template for the Django TemplateView
    template_name = "some_view_template.html"

You need a view to handle the login (with URL in settings.LOGIN_URL), containing a form with a hidden field called next. This field has to be set by a context variable to the page to go to after successful login.

If all views inherit from the base mixin (MyDefaultMixin in my code above), it will automatically check that the user is logged in iv the view contain an attribute called login_required and that is set to True.

There might be better ways to do this, but this is what I did and it worked very well.

4👍

have a look at middleware. these are functions run at various points in the request cycle, e.g. before each view is called.

since you may want to exclude certain views from this, i’d look at e.g. how the csrf middleware works, together with the csrf_exempt decorator.

see [SOURCE]/django/views/decorators/csrf.py and [SOURCE]/django/middleware/csrf.py

👤second

Leave a comment