Метод has_change_permission
Метод has_change_permission применяется к экземпляру ModelAdmin и определяет, может ли пользователь изменять объекты данной модели в административной панели. Метод вызывается при отображении списка объектов, при переходе на страницу редактирования и при попытке сохранения изменений. Он принимает объект запроса и опционально конкретный объект модели, что позволяет гибко настраивать права на уровне отдельных записей.
Синтаксис
class MyModelAdmin(admin.ModelAdmin):
def has_change_permission(self, request, obj=None):
# логика проверки
return True или False
Метод должен возвращать True, если пользователь может изменять объект, и False в противном случае. Параметр obj принимает экземпляр модели или None при проверке общей возможности изменения для всей модели.
Пример . С проверкой группы пользователей
Разрешим изменение объектов только пользователям, входящим в группу "content_managers":
from django.contrib import admin
from django.contrib.auth.models import Group
from myapp.models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ['title', 'status']
def has_change_permission(self, request, obj=None):
# Суперпользователи всегда имеют доступ
if request.user.is_superuser:
return True
# Проверяем принадлежность к группе
content_group = Group.objects.get(name='content_managers')
if content_group in request.user.groups.all():
return True
return False
Теперь только суперпользователи и участники группы "content_managers" могут редактировать статьи. Остальные пользователи увидят, что кнопка "Изменить" отсутствует или недоступна.
Пример . С ограничением по статусу объекта
Запретим изменение объектов, которые уже опубликованы, чтобы избежать случайной правки важных материалов:
from django.contrib import admin
from myapp.models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ['title', 'status']
readonly_fields = ['status']
def has_change_permission(self, request, obj=None):
# Если объект не передан - разрешаем (проверка списка объектов)
if obj is None:
return True
# Запрещаем изменение опубликованных статей
if obj.status == 'published':
return False
return True
Результат выполнения кода:
"Change permission for draft article: True"
"Change permission for published article: False"
Теперь администратор не может изменять опубликованные статьи, но может работать с черновиками. Поле status добавлено в readonly_fields для наглядности.
Пример . С комбинированной проверкой
Создадим более сложную логику: разрешим изменение только авторам их собственных статей или менеджерам, но с ограничением на изменение статуса публикации:
from django.contrib import admin
from django.contrib.auth.models import Group
from myapp.models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'status']
fields = ['title', 'content', 'status']
def has_change_permission(self, request, obj=None):
# Суперпользователи имеют полный доступ
if request.user.is_superuser:
return True
# Для проверки списка объектов
if obj is None:
return True
# Автор может изменять свои статьи
if obj.author == request.user:
return True
# Менеджеры могут изменять любые статьи, но не статус
manager_group = Group.objects.get(name='managers')
if manager_group in request.user.groups.all():
# Запоминаем ограничение в запросе для save_model
request._status_change_restricted = True
return True
return False
В этом примере авторы имеют полный доступ к своим статьям, а менеджеры - ко всем, но с ограничением на изменение статуса (это можно дополнительно обработать в методе save_model).
Смотрите также
-
метод
has_add_permission,
который проверяет право на добавление объектов -
метод
has_delete_permission,
который проверяет право на удаление объектов -
метод
get_queryset,
который фильтрует объекты для отображения в админке -
метод
save_model,
который обрабатывает сохранение объекта и может дополнять проверку прав