2c76bea1e6
- Permissions are grouped by content type and displayed under its verbose_name_plural. - Default permissions appear before custom ones. - Use `permissions-field` class to enhance display.
77 lines
2.6 KiB
Python
77 lines
2.6 KiB
Python
import re
|
|
from itertools import groupby
|
|
from operator import attrgetter
|
|
|
|
from django import forms
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from .models import Group, Permission
|
|
|
|
DEFAULT_PERMS = ['view', 'add', 'change', 'delete']
|
|
|
|
DEFAULT_PERMS_LABELS = {
|
|
'view': _("Voir"),
|
|
'add': _("Ajouter"),
|
|
'change': _("Modifier"),
|
|
'delete': _("Supprimer"),
|
|
}
|
|
|
|
|
|
class GroupsField(forms.ModelMultipleChoiceField):
|
|
def __init__(self, **kwargs):
|
|
kwargs.setdefault('queryset', Group.objects.all())
|
|
kwargs.setdefault('widget', forms.CheckboxSelectMultiple)
|
|
super().__init__(**kwargs)
|
|
|
|
|
|
class BasePermissionsField(forms.ModelMultipleChoiceField):
|
|
def __init__(self, **kwargs):
|
|
kwargs.setdefault('widget', forms.CheckboxSelectMultiple(attrs={
|
|
'field_class': 'permissions-field',
|
|
}))
|
|
super().__init__(**kwargs)
|
|
|
|
# Contain permissions grouped by `ContentType`. Used as choices for
|
|
# this field.
|
|
grouped_choices = []
|
|
|
|
for ct, perms in groupby(self.queryset, attrgetter('content_type')):
|
|
model_opts = ct.model_class()._meta
|
|
choices = []
|
|
|
|
# This helps for the default permissions, if they exists, to appear
|
|
# at the beginning of the permissions list and use custom labels.
|
|
reg_defaults_p = re.compile(
|
|
r'^(?P<p_type>({defaults}))_{model_name}$'
|
|
.format(
|
|
defaults='|'.join(DEFAULT_PERMS),
|
|
model_name=model_opts.model_name,
|
|
)
|
|
)
|
|
next_default_pos = 0
|
|
|
|
for p in perms:
|
|
match = reg_defaults_p.match(p.codename)
|
|
if match:
|
|
# `p` is a default permission. Use shorter label and insert
|
|
# after the last default permission seen in `choices`.
|
|
p_type = match.group('p_type')
|
|
choices.insert(
|
|
next_default_pos,
|
|
(p.id, DEFAULT_PERMS_LABELS[p_type])
|
|
)
|
|
next_default_pos += 1
|
|
else:
|
|
# Non-default permissions. Use the permission description,
|
|
# instead of its `__str__`.
|
|
choices.append((p.id, p.name))
|
|
|
|
grouped_choices.append((model_opts.verbose_name_plural, choices))
|
|
|
|
self.choices = grouped_choices
|
|
|
|
|
|
class CorePermissionsField(BasePermissionsField):
|
|
def __init__(self, **kwargs):
|
|
kwargs.setdefault('queryset', Permission.kfetcore.all())
|
|
super().__init__(**kwargs)
|