How can I use Django permissions without defining a content type or model?

Chewie picture Chewie · Dec 18, 2012 · Viewed 26.7k times · Source

I'd like to use a permissions based system to restrict certain actions within my Django application. These actions need not be related to a particular model (e.g. access to sections in the application, searching...), so I can't use the stock permissions framework directly, because the Permission model requires a reference to an installed content type.

I could write my own permission model but then I'd have to rewrite all the goodies included with the Django permissions, such as:

I've checked some apps like django-authority and django-guardian, but they seem to provide permissions even more coupled to the model system, by allowing per-object permissions.

Is there a way to reuse this framework without having defined any model (besides User and Group) for the project?

Answer

Dmitry picture Dmitry · Jun 23, 2016

For those of you, who are still searching:

You can create an auxiliary model with no database table. That model can bring to your project any permission you need. There is no need to deal with ContentType or create Permission objects explicitly.

from django.db import models
        
class RightsSupport(models.Model):
            
    class Meta:
        
        managed = False  # No database table creation or deletion  \
                         # operations will be performed for this model. 
                
        default_permissions = () # disable "add", "change", "delete"
                                 # and "view" default permissions

        permissions = ( 
            ('customer_rights', 'Global customer rights'),  
            ('vendor_rights', 'Global vendor rights'), 
            ('any_rights', 'Global any rights'), 
        )

Right after manage.py makemigrations and manage.py migrate you can use these permissions like any other.

# Decorator

@permission_required('app.customer_rights')
def my_search_view(request):
    …

# Inside a view

def my_search_view(request):
    request.user.has_perm('app.customer_rights')

# In a template
# The currently logged-in user’s permissions are stored in the template variable {{ perms }}

{% if perms.app.customer_rights %}
    <p>You can do any customer stuff</p>
{% endif %}