Permission String
The documentation for Django authentication (e.g. https://docs.djangoproject.com/en/2.2/topics/auth/default/#permissions-and-authorization) talks about allowing code to restrict access to models through a vague notion of a “permission.”
Read further and you kinda get the idea that a “permission” in most practical applications is a string. Whether you’re using explicit checks like user.has_perm(permission)
or decorators like @permission_required(permission)
or class properties for the PermissionRequiredMixin
like this (taken right out from the page):
from django.contrib.auth.mixins import PermissionRequiredMixin
class MyView(PermissionRequiredMixin, View):
permission_required = 'polls.can_vote'
The problem with using strings is that the burden of getting things correct lies heavily on the documentation. A basic question, then, is that: given a model created in the app, what permission string should you use to work with the Authentication system to guard the model’s access?
Extremely Underrated Section
The short section on “Default permissions” (https://docs.djangoproject.com/en/2.2/topics/auth/default/#default-permissions) initially looks innocuous enough. However, it turns out that the section is the key to using permissions on models (custom permissions notwithstanding).
If you’re in a hurry to get permissions working on some models, you’d be forgiven for searching on the page and jump directly to the section on the “permission_required
” decorator (and the section on PermissionRequiredMixin
immediately after) where they show examples of using permissions of the form:
<model>.can_<action>
For example, 'polls.can_vote'
is used throughout these sections to indicate the ability to “vote” on the “polls” model.
You may infer from that permissions like:
polls.can_add
polls.can_change
polls.can_delete
polls.can_view
because–oh–you skimmed some section earlier on the helper functions has_view_permission()
, has_add_permission()
, etc.
Well. Turns out these permission values will not work because the default permissions on models do not in fact follow this convention.
UPDATE: the Django 3.0 documentation, fortunately, fixed this by giving actual working values (e.g. “‘polls.add_choice
‘”).
Convention on Default Permission Codenames
That brings us back to the section “Default permissions,” that small section of about 20 lines on a page of thousands.
Codename
Firstly, a permission (as can be seen in the table auth_permission
) has an attribute “codename,” and that is what is used to communicate the permission being tested on.
Testing Against Codenames
All methods of working on permissions will operate on these codename
values:
Model.has_perm(codename) and its friends from ModelAdmin: has_view_permission, has_add_permission, has_change_permission, and has_delete_permission
django.contrib.auth.decorators.permission_required decorator
PermissionRequiredMixin mixin class
Convention of Default Permission Codenames
Finally, the convention of the codename (as documented in that Default permissions section) is:
<app_label>.<action>_<model name>
- The app_label is the
name
of theAppConfig
for your app, most likely defined in apps.py of your app. - The action is one of ‘add’, ‘change’, ‘delete’, and (with Django version 2.1 or higher) ‘view.’
- The model_name is the lower case form of your model name in the DB.
So if I had a Polls app with a model Posting,
polls/apps.py:
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = 'polls'
possible permission codenames are:
- polls.view_posting
- polls.add_posting
- polls.change_posting
- polls.delete_posting
When in Doubt, Check the DB
If you’re not sure, you can always check the auth_permission table in your DB:
select name, codename from auth_permission;
The name is what the Admin pages use to show the permission to assign/unassign. The codename is, of course, the permission string you would use in code.