admin.py django отфильтровать по permissions вывод actions, filter и list_display.
Давайте представим ситуацию когда нужно создать узкоспециализированную учётную запись в django которой будут доступны лишь ограниченный функционал административной панели.
Во первых используя штатный механизм django мы создадим группу в которую мы добавим только нужные разрешения для пользователей входящих в эту группу.
А далее на основании этих разрешений мы сможем дополнительно кастомизировать функционал и вывод информации в админке для таких пользователей.
сначала соберём нужную информацию, для этого заходим в окружение вашего проекта django
находясь в нужном месте пути, вашего проекта выполняем
source venv/bin/activate
python manage.py shell
вводим построчно, соблюдая правильные отступы
☯
Terminal:
⌕
≡
✕
from django.contrib.auth.models import Group
#если у вас кастомный юзер, как у меня, в качестве логина только с email без имени(как такого сделать в другой статье) или
#from users.models import User
from users.models import CustomUser as User
user = User.objects.get(email='yourmail@mail.com')
groups = user.groups.all()
for group in groups:
group_name = group.name
group_id = group.id
print(group_name)
print(group_id)
#Теперь в оболочке, импортируйте модель Permission из модуля django.contrib.auth.models:
from django.contrib.auth.models import Permission
permissions = Permission.objects.filter(content_type__app_label='your_app')
for permission in permissions:
print(permission.codename)
Так мы получим все имена групп в которых состоит этот пользователь и узнаем нужный id группы, которую мы планируем ограничить. либо можно будет ограничивать пользователя и на основании отстуствия определённых прав, узнать какие права вообще существуют можно так.
А также вывели кодовые имена (permission_codename) доступных разрешений для указанного приложения. Обратите внимание, что вы должны заменить 'your_app' на фактическое имя вашего приложения.
Давайте рассмотрим сперва ограничение по имени доступных разрешений, а потом рассмотрим по id группы, но принцип один и тот же.
В данном случае я хочу убрать доступ к некоторым из actions, в админке, для такого набора разрешений.
допустим в нашем admin.py есть модель которую мы выводим в админке
☯
Terminal:
⌕
≡
✕
from django.contrib import admin
from .models import YourModel1, YourModel2
#например одно из действий
def dublicate_ad(modeladmin, request, queryset):
# клонирование выбранных объектов модели
for ad in queryset:
ad.pk = None
ad.save()
dublicate_ad.short_description = "Дублировать объект"
#Создаём новый класс CustomModelAdmin, наследуемый от ModelAdmin, и переопределим метод get_actions(),
#для определения списка действий, доступных пользователю:
class CustomModelAdmin(admin.ModelAdmin):
def get_actions(self, request):
actions = super().get_actions(request)
#создаём два списка, пустой и список с именами действий которые мы желаем скрыть
actions_to_remove = []
hidden_actions = ['dublicate_ad','render_to_pdf_ALL','export_admin_action']
#наполняем пустой список теми действиями, которые попадают в это условие, т.е. находятся в списке скрываемых и при этом у пользователя отсутствуют нужные права, которые мы явно тут укажем
for action in actions:
if not request.user.has_perm('your_app.change_title') and action in hidden_actions:
actions_to_remove.append(action)
#теперь на основании этого созданного списка удаляем действия которые находятся в основном списке действий. так нужно делать чтобы итерируемый массив не менялся в количестве элементов по ходу итераций в этом цикле...
for action in actions_to_remove:
del actions[action]
return actions
#Зарегистрируйте модели с использованием нового класса администратора в функции admin.site.register():
admin.site.register(YourModel1, CustomModelAdmin)
admin.site.register(YourModel2, CustomModelAdmin)
Мы идём таким путём, чтобы использовать массив request с нужными нам данными
Фактически метод get_actions() вызывается автоматически во время отображения списка действий (actions) в административной панели Django.
Теперь, давайте ещё кое-что сделаем. Мы можем добавить в отображаемые в админке, связь "один ко многим" (ForeignKey), чтобы вывести поле, связанное с помощью этой связи, в административной панели с помощью атрибута list_display в классе ModelAdmin.
Предположим, у вас есть модель Zakaz, имеющая внешний ключ foreign_key на модель Investor.
Чтобы вывести поле, связанное с Innvestor, с помощью list_display, вам нужно сначала определить метод в классе ModelAdmin, который будет возвращать значение этого поля. Затем это поле можно добавить в list_display.
☯
Terminal:
⌕
≡
✕
#например используем такую функцию проверки наличия id в списке объектов, чтобы по id группы сделать нужное действие
def checkID(id,objects):
result = False
for obj in objects:
if id == obj.id:
result = True
break
return result
class CustomModelAdmin(admin.ModelAdmin):
...
...
...
list_display = ('pk','cert_tag','investor','investor_tel')
#допустим мы решили разрешить видеть такое поле определённой группе у которой id=2, тогда проверим если у текущего пользователя есть такая группа
def investor_tel(self, obj):
if checkID(2,request.user.groups.all()):
return obj.investor.phone
else
return 'нет прав, чтобы это видеть'
investor_tel.short_description = 'Телефон пользователя' # Опционально, для отображения пользовательского заголовка в колонке
аналогичным образом если у пользователя есть разрешения или он состоит в группе с id 2 покажем разные фильтры
☯
Terminal:
⌕
≡
✕
def checkID(id,objects):
result = False
for obj in objects:
if id == obj.id:
result = True
break
return result
class CustomModelAdmin(admin.ModelAdmin):
...
...
...
# просто скрыть один или несколько фильтров в зависимости от разрешения пользователя
def get_list_filter(self, request):
if request.user.has_perm('shop.can_change_filter') or checkID(2,request.user.groups.all()):
# Если у пользователя есть разрешение "can_change_filter", показать такие фильтры
return ('resendcert','participation','investor',AggregatorFilter,'status','status_pay')
else:
# иначе такие
return ('email_send','place','date_exec','date_order'',')
как вы уже наверное поняли мы переопределяем и используем существующие методы, которые автоматически вызываются в django get_list_filter, get_actions и таким образом решили свои вопросы.
-
Создано 23.06.2023 17:00:00
-
Roman Sakhno

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.