Better display of objects of BasePermissionsField
- 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.
This commit is contained in:
parent
07f1a53532
commit
2c76bea1e6
1 changed files with 55 additions and 3 deletions
|
@ -1,7 +1,21 @@
|
||||||
|
import re
|
||||||
|
from itertools import groupby
|
||||||
|
from operator import attrgetter
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from .models import Group, Permission
|
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):
|
class GroupsField(forms.ModelMultipleChoiceField):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
@ -12,11 +26,49 @@ class GroupsField(forms.ModelMultipleChoiceField):
|
||||||
|
|
||||||
class BasePermissionsField(forms.ModelMultipleChoiceField):
|
class BasePermissionsField(forms.ModelMultipleChoiceField):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
kwargs.setdefault('widget', forms.CheckboxSelectMultiple)
|
kwargs.setdefault('widget', forms.CheckboxSelectMultiple(attrs={
|
||||||
|
'field_class': 'permissions-field',
|
||||||
|
}))
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def label_from_instance(self, obj):
|
# Contain permissions grouped by `ContentType`. Used as choices for
|
||||||
return obj.name
|
# 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):
|
class CorePermissionsField(BasePermissionsField):
|
||||||
|
|
Loading…
Reference in a new issue