Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
186 lines (134 sloc) 4.47 KB


Coverage Status PyPI

Role-based permissions system for Django. Everyone wears a different hat, some people wear multiple.

In a nutshell, django-hats is a reusable app, which doesn't try to re-invent the wheel by having Django Groups as its foundation. It provides a compact collection of easy to use patterns/utilities for role, and permission, based checks in CBVs and templates. They have the advantages of being: pragmatically defined, performant, clear syntax, and are well tested/documented!

Quick Start

Install with pip:

pip install django-hats

Or, getting the latest build:

pip install git+git://

Add django_hats to your INSTALLED_APPS:


Create in any registered applications in your Django project:

from django_hats.roles import Role

class Scientist(Role):
    class Meta:
        permissions = ('change_subject', 'change_specimen')

class GeneticCounselor(Role):

Synchronize your database with defined roles:

python synchronize_roles

You're ready to go! Start defining permissions and securing your application!

Working with roles

Pragmatically assigning/removing/viewing Permission to role:

>>> Scientist.add_permissions(perm_1, perm_2, ...)
>>> GeneticCounselor.remove_permissions(perm_3)
>>> Scientist.get_permissions()
[<Permission 'change_subject'>, <Permission 'change_specimen'>]

Assigning/removing roles for a user(works with custom user models):

>>> user = User.objects.first()
>>> Scientist.assign(user)
>>> Scientist.remove(user)

Then checking if a user has a role, or multiple roles:

>>> from django_hats.utils import check_membership
>>> Scientist.check_membership(user)
>>> GeneticCounselor.check_membership(user)
>>> check_membership(user, Scientist)
>>> check_membership(user, [Scientist, GeneticCounselor])
>>> check_membership(user, [Scientist, GeneticCounselor], any=True)

List users with a given role:

>>> Scientist.get_users()
[<User 'Mike Hearing'>, <User 'Scientist_1'>]

Retrieving roles pragmatically:

>>> from django_hats.roles import RoleFinder
>>> RoleFinder.by_user(user)
[<class 'Scientist'>, ]
>>> RoleFinder.by_name('genetic_counselor')
<class 'GeneticCounselor'>
>>> RoleFinder.by_group(group)
<class 'Scientist'>


Enforcing roles on the view:

from django.views.generic import TemplateView
from django_hats.mixins import RoleRequiredMixin

from app.roles import GeneticCounselor, Scientist

class ProtectedGeneticReport(RoleRequiredMixin, TemplateView):
    role_required = GeneticCounselor
    template_name = 'template.html'

class ProtectedGeneticFiles(RoleRequiredMixin, TemplateView):
    # Works with existing Django `PermissionRequiredMixin`
    permission_required = ('change_subject', 'change_specimen')
    role_required = (GeneticCounselor, Scientist)
    role_required_any = True
    template_name = 'template.html'


Checking roles in the template like permissions:
NOTE: This is the reccomended way to check for roles in the template



{% if roles.scientist %}PROTECTED CONTENT!{% endif %}

{% if roles.genetic_counselor %}NOTE: Class names are converted to snake_case if not specified in{% endif %}

Checking roles in the template with filter tag:
NOTE: This works without the context processor, and is not required when using the context processor, if thats your thing

{% load roles %}

{% if user|has_role:'scientist' or user|has_role:genetic_counselor_role %}PROTECTED CONTENT!{% endif %}



  • sender: django-hats AppConfig

Management Commands

Synchronize roles/permissions from the database:

python synchronize_roles

Migrate a role which the class name/name has changed:

python migrate_role --old=OldRoleClass --new=NewRoleClass

Remove old roles/permissions from the database(only post migration if a name change occured):

python cleanup_roles
You can’t perform that action at this time.