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)

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