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:
- The possibility to assign permissions to users and groups.
- The
permission_required
decorator. User.has_perm
and related user methods.- The
perms
template variable. - ...
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?
Fix for Chewie's answer in Django 1.8, which as been requested in a few comments.
It says in the release notes:
So it's the 'name' in reference in ContentType that the uses not in GlobalPermissions.
When I fix it I get the following:
The GlobalPermissionManager class is unchanged but included for completeness.
Following Gonzalo's advice, I used a proxy model and a custom manager to handle my "modelless" permissions with a dummy content type.
Instead of writing and running this code which inserts records into the database you could just insert the records into your database (obviously editing the primary and foreign keys as needed)
And then in your application admin you would have the ability to assign 'Is Staff Member' to your users or groups. To check this permission in your class you would write
Django's
Permission
model requires aContentType
instance.I think one way around it is creating a dummy
ContentType
that isn't related to any model (theapp_label
andmodel
fields can be set to any string value).If you want it all clean and nice, you can create a
Permission
proxy model that handles all the ugly details of the dummyContentType
and creates "modelless" permission instances. You can also add a custom manager that filters out allPermission
instances related to real models.This is alternative solution. First ask yourself: Why not create a Dummy-Model which really exists in DB but never ever gets used, except for holding permissions? That's not nice, but I think it is valid and straight forward solution.
Above solution has the benefit, that you can use the variable
Permissions.can_search_blue_flower
in your source code instead of using the literal string "my_app.can_search_blue_flower". This means less typos and more autocomplete in IDE.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.
Right after
manage.py migrate
you can use these permissions like any other.