Django per request permission using Django's Auth Framework

Django has a very stable auth system that includes a permission sub framework as well. It allows user to work with object level permissions which makes sense if every view you have offers up an object to work with.

However when you don't want to get into object level permissions and are just concerned with decorating the View you can still use the Django auth framework.

Permissions require a content type associated with it in order to work.

from myapp.models import BlogPost  
from django.contrib.auth.models import Permission  
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)  
permission = Permission.objects.create(codename='can_publish',  
                          name='Can Publish Posts',
                          content_type=content_type)

So people found a workaround. Create a dummy content type (by creating a dummy model). Here's the post that discusses that. Really smart. I used it for our server and it worked like a charm. I created a separate app to keep the view/mixins and the models away from rest of the app.

Now, we have a lot of Function Based Views but I prefer Class Based Views. Somehow inheritance always seems more logical to me. So in order to check for permissions I created a mixin that checks if the user belongs to a certain group. People recommend using user_passes_test. I prefer a simple exists()

from logging import getLogger  
try:  
    from functools import wraps
except:  
    from django.utils.functional import wraps
from django.http import HttpResponseForbidden  
from django.core.exceptions import ImproperlyConfigured


log = getLogger(__name__)


# Create your views here.
class PermissionsMixin(object):  
    permissions = None

    def __init__(self):
        if not self.permissions:
            raise ImproperlyConfigured("Permissions Need to be set for the view")

    def dispatch(self, request, *args, **kwargs):
        if request.method.lower() in self.permissions.keys():
            if request.user.groups.filter(name__in=self.permissions.get(request.method.lower())).exists():
                return super(PermissionsMixin, self).dispatch(request, *args, **kwargs)
            return HttpResponseForbidden()

Permissions need to be set as follows in the Child class:
permissions = {u'get': ['Group1', 'Group2'], u'post': ['Group3', 'Group4']}

This decorates the type of request and checks if that request type is being invoked and checks if user is in the list of groups provided on the child class.

Works like a charm.