Разрешения на уровне строки в django
Есть ли способ сделать разрешения на уровне строк в django? Я думал, что это не так, а просто заметили это в документах:
Разрешения могут быть установлены не только для каждого типа объекта, но и для каждого конкретный экземпляр объекта. Используя has_add_permission(), Имеются методы has_change_permission() и has_delete_permission() классом ModelAdmin, можно настроить разрешения для разные экземпляры объектов того же типа.
https://docs.djangoproject.com/en/dev/topics/auth/
Но я не вижу никакой документации о том, как реально реализовать разрешения на экземпляр
Ответы
Ответ 1
Для приложения, которое я создаю, я хочу предоставить разрешение на уровне строк через простой декоратор. Я могу сделать это, потому что условие заключается только в том, является ли request.user владельцем объекта модели.
Кажется, что работает:
from functools import wraps
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
def is_owner_permission_required(model, pk_name='pk'):
def decorator(view_func):
def wrap(request, *args, **kwargs):
pk = kwargs.get(pk_name, None)
if pk is None:
raise RuntimeError('decorator requires pk argument to be set (got {} instead)'.format(kwargs))
is_owner_func = getattr(model, 'is_owner', None)
if is_owner_func is None:
raise RuntimeError('decorator requires model {} to provide is_owner function)'.format(model))
o=model.objects.get(pk=pk) #raises ObjectDoesNotExist
if o.is_owner(request.user):
return view_func(request, *args, **kwargs)
else:
raise PermissionDenied
return wraps(view_func)(wrap)
return decorator
Вид:
@login_required
@is_owner_permission_required(Comment)
def edit_comment(request, pk):
...
Urls:
url(r'^comment/(?P<pk>\d+)/edit/$', 'edit_comment'),
Модель:
class Comment(models.Model):
user = models.ForeignKey(User, ...
<...>
def is_owner(self, user):
return self.user == user
Любые отзывы или замечания приветствуются.
Пол Борман
Ответ 2
Способы, о которых говорят документы, позволят вам ограничить доступ к определенным объектам в admin. Каждому методу передается объект в игре, который вы можете использовать для определения того, может ли пользователь получить к нему доступ, возвращая либо True
, либо False
.
class MyModelAdmin(admin.ModelAdmin):
...
def has_add_permission(self, request):
# This one doesn't get an object to play with, because there is no
# object yet, but you can still do things like:
return request.user.is_superuser
# This will allow only superusers to add new objects of this type
def has_change_permission(self, request, obj=None):
# Here you have the object, but this is only really useful if it has
# ownership info on it, such as a `user` FK
if obj is not None:
return request.user.is_superuser or \
obj.user == request.user
# Now only the "owner" or a superuser will be able to edit this object
else:
# obj == None when you're on the changelist page, so returning `False`
# here will make the changelist page not even viewable, as a result,
# you'd want to do something like:
return request.user.is_superuser or \
self.model._default_manager.filter(user=request.user).exists()
# Then, users must "own" *something* or be a superuser or they
# can't see the changelist
def has_delete_permission(self, request, obj=None):
# This pretty much works the same as `has_change_permission` only
# the obj == None condition here affects the ability to use the
# "delete selected" action on the changelist
Ответ 3
Сантехника там (это со дна той же страницы, которую вы связали):
Обработка разрешений объектов
Структура разрешения Django имеет основание для прав объекта, хотя реализация отсутствует для этого в ядре. Это означает, что проверка прав объекта всегда будет возвращать False или пустой список (в зависимости от проверки выполнено). Бэкэнд аутентификации получит ключевое слово параметры obj и user_obj для каждого связанного с объектами разрешения метод и может при необходимости вернуть разрешение на уровне объекта.
Но реализация по умолчанию не предусмотрена. Поскольку это общая тема; есть много ответов на SO. Проверьте вправо, и вы увидите некоторые из них.
Основная идея состоит в том, чтобы просмотреть сетку разрешений django пакетов и выбрать реализацию разрешений уровня объекта. Мне лично нравится django-guardian.
Ответ 4
Я разработал решение этой проблемы с использованием представлений класса Django.
Ознакомьтесь с моей статьей Django Generic Class Based Views с проверкой прав на уровне объектов.
Ответ 5
Существует большое количество приложений "разрешений" для django доступно на PyPi
Например, вы можете посмотреть django-object-permission.
В документации, на которую ссылается документация, есть функциональность для реализации разрешений. И люди сделали это, создав приложения для этого.