Code


Version 1 (modified by djangoproject.com@…, 8 years ago) (diff)

First version

Sometimes it is useful to only allow users from a certain group to login.

The main problem with that idea is that you can't actually check if the user is in the required group before he logs in. This is a kind of chicken and egg problem in django because as the anonymous user you don't have enough rights to look the necessary information up.

The solution/workaround to the problem is:

a) modified decorator for user_passes_test from django.contrib.auth.decorator:

from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
from django.http import HttpResponseRedirect, Http404

def user_passes_mytest(test_func, login_url=LOGIN_URL):
    def _dec(view_func):
        def _checklogin(request, *args, **kwargs):
            try:
                if test_func(request.user):
                    return view_func(request, *args, **kwargs)
                return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path
())))
            except:
                raise Http404
        return _checklogin
    return _dec

b) one central login view (and template) for every (django) application:

from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import Group, SESSION_KEY
from django.shortcuts import render_to_response

@login_required
def index(request):
    custgroup = Group.objects.get(name="thegroupyouneed") # Replace group name here!
    if custgroup in request.user.groups.all():
        return render_to_response('myapp/templates/index.html') # This is the welcome screen after a successful login
    else:
        try:
            del request.session[SESSION_KEY]
        except:
            pass
        return render_to_response('registration/notallowed.html') # This is the 'not allowed' screen wich 
                                                                  # should be shown if the user is not in the correct group

and finally c) the other views using our new decorator:

REQUIRED_GROUP = Group.objects.get(name="thegroupyouneed") # Replace group name here!

@user_passes_mytest(lambda u: REQUIRED_GROUP in u.groups.all())
def someviewhere(request):
    return render_to_response('myapp/templates/someviewhere.html')

That's it. Enjoy!