Bootstrap

admin.py django отфильтровать по permissions вывод actions, filter и list_display.

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 и таким образом решили свои вопросы.

Копирование материалов разрешается только с указанием автора Roman Sakhno и индексируемой прямой ссылкой на сайт (http://itdid.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/sahroman.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/sahroman.

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как настроить свой компьютер

  2. Текстовая ссылка:

    Она выглядит вот так: Как настроить свой компьютер

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

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

крипто-донат, на развитие сайта itdid.ru:

В новом окне с терминалом itdid.ru, введите любую сумму: