24 декабря 2018 г.

django: фильтр нужных разрешений юзера в админке

В админке Django всегда делаю чтобы в настройках профиля и настройках группы светились только нужные, используемые в логике пермишены (например, свои или какие-то отдельные стандартные).
Иначе их обычно слишком много и непонятно какие в реальности имеют смысл.
Просто перегружаются Admin-классы и формы в них, где фильтруется ModelForm.queryset у нужного поля формы.

admin.py
from django.contrib.auth.models import User, Group, Permission
from django.contrib.auth.admin import UserAdmin, GroupAdmin
from django.contrib.auth.forms import UserChangeForm
from django.db.models import Q
from django import forms

USED_PERMS = [
    'reports.add_report',
    'reports.change_report',
    'app2.custom_perm',
]

def qs_perm_filter(qs):
    ups = [up.split('.') for up in USED_PERMS]
    q_expressions = [Q(content_type__app_label=up[0], codename=up[1]) for up in ups]
    return qs.filter(reduce(operator.or_, q_expressions))
    
# наследуем форму (у меня там ещё много помимо этого), также см. нужную model
class UserProfileChangeForm(UserChangeForm):
    class Meta:
        model = UserProfile
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(UserProfileChangeForm, self).__init__(*args, **kwargs)

        f = self.fields.get('user_permissions')
        if f is not None:
            f.queryset = qs_perm_filter(f.queryset)

# наследуем кастомный UserAdmin
class UserProfileAdmin(UserAdmin):
    ...
    form = UserProfileChangeForm
    ...
    
# показываем профиль, родной User не показываем
admin.site.unregister(User)
admin.site.register(UserProfile, UserProfileAdmin)

# для групп тоже аналогично всё
class MyGroupAdminForm(forms.ModelForm):
    class Meta:
        model = Group
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(MyGroupAdminForm, self).__init__(*args, **kwargs)

        f = self.fields.get('permissions')
        if f is not None:
            f.queryset = qs_perm_filter(f.queryset)


class MyGroupAdmin(GroupAdmin):
    form = MyGroupAdminForm

admin.site.unregister(Group)
admin.site.register(Group, MyGroupAdmin)

Также для бонуса - вынос пермишенов пользователя в таблицу с юзерами в админке. Из списка видно кто и каким правами обладает, там все группы, персональные права, указание на доступ к админке и т.д:

class UserProfileAdmin(UserAdmin):
    ...
    list_display = (..., 'custom_groups', ...)
    ...
    # список групп юзера через запятую, указание что персонал итд
    def custom_groups(self, obj):
        cg = [g.name for g in obj.groups.all()]
        if obj.is_superuser:
            cg.insert(0, '[all perms]')
        if obj.is_staff:
            cg.insert(0, '[staff]')
        if obj.user_permissions.count() > 0:
            listperm = ',\n'.join(up.__str__() for up in obj.user_permissions.all())
            cg.append('[Personal perms]' % listperm)
        return ', '.join(cg)
    custom_groups.short_description = 'User perms'
    custom_groups.allow_tags = True

Комментариев нет:

Отправить комментарий