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 from django.contrib.auth import 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!