Quickstart
Dependencies
django >= 2.2
Installation
Install the latest tarball:
pip install https://git.m-stelzer.de/knoppo/django-model-permissions/-/archive/master/django-model-permissions-master.tar.gz
Add the app to INSTALLED_APPS:
INSTALLED_APPS = [ # ... 'model_permissions', ]
Replace AUTHENTICATION_BACKENDS:
AUTHENTICATION_BACKENDS = [ 'model_permissions.backends.ObjectModelBackend', ]
This replaces the default backend with an extended version. (See Permission Function)
If you don’t want to retain django’s user and group permissions, use the ObjectBackend instead:
AUTHENTICATION_BACKENDS = [ 'model_permissions.backends.ObjectBackend', ]
Optional: Redirect all PermissionDenied errors to
LOGIN_URL
:MIDDLEWARE = [ # ... 'model_permissions.middleware.RedirectMiddleware', ]
Usage
Create a Permission Function called get_permissions as a method on your model:
It should return a list of permissions the given user has for this object.
class MyModel(models.Model): owner = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE) def get_permissions(self, user): if user.is_anonymous: return permissions = ['myapp.add_mymodel'] if not user.is_staff and not user == self.owner: return permissions return permissions + [ 'myapp.change_mymodel', 'myapp.delete_mymodel', ]
Use the model_permissions views or mixins:
Since it seems to be very hard to inject the object permissions in a context_processor, django-model-permissions comes with ready-to-use views and mixins:
from model_permissions.views import CreateView, UpdateView, DeleteView class MyModelCreateView(CreateView): model = MyModel class MyModelCreateView(UpdateView): model = MyModel fields = ('name', 'description', 'owner') required_permission = 'myapp.change_mymodel' class MyModelCreateView(DeleteView): model = MyModel required_permission = 'myapp.delete_mymodel'
The main functionality is split into 2 mixins.
Tip
Use the
model_permissions.views.PermissionMixin
if you want both.The
model_permissions.views.PermissionContextMixin
adds a'object_perms'
variable to the template context. Use it if your view is public and you just want to access the permissions in the template.from model_permissions.views import PermissionContextMixin from django.views.generic import DetailView from myapp.models import MyModel class MyModelDetailView(PermissionContextMixin, DetailView): model = MyModel fields = ('name', 'description', 'owner')
Use the
model_permissions.views.RequirePermissionMixin
to restrict access to a view based on object permissions:from model_permissions.views import UpdateView from myapp.models import MyModel class MyModelDetailView(UpdateView): model = MyModel required_permission = 'myapp.change_mymodel' fields = ('name', 'description', 'owner')
Use permissions in your templates:
If you’re using the
model_permissions.views.PermissionContextMixin
or one of its subclasses your context will containobject_perms
and<model_label>_perms
variables:Note
The second example also shows the usage of Related Permissions.
{# forum_detail.html #} {% if forum_perms.myforum.change_forum %} <a href="{% url "myforum:change_forum" forum.pk %}">Edit</a> {% endif %} {# or #} {% if object_perms.myforum.add_thread %} <a href="{% url "myforum:add_thread" forum.pk %}">Add Thread</a> {% endif %}
To get permissions for another object or in views that are not subclassing
model_permissions.views.PermissionContextMixin
you can use theget_perms
template tag:Without argument it will use the
object
variable in the context. The resulting perms lookup dict will not contain any object permissions if there is no object.{# thread_detail.html #} {% load model_permissions %} {% get_perms as thread_perms %} <h1> {% if thread_perms.myforum.change_thread %} <a href="{% url "myforum:change_thread" thread.pk %}">{{ thread }}</a> {% else %} {{ thread }} {% endif %} </h1> <ul> {% for post in posts %} {% get_perms post as post_perms %} <li> <h4> {% if post_perms.myforum.change_post %} <a href="{% url "myforum:change_post" post.pk %}">{{ post }}</a> {% else %} {{ post }} {% endif %} </h4> <p>{{ post.text }}</p> </li> {% endfor %} </ul>