Разрешение представления набора django rest framework на основе метода

Итак, я пишу свой первый проект с DRF, и у меня возникли проблемы с настройкой разрешений для моих наборов просмотра. У меня уже есть аутентификация, работающая с djangorestframework-jwt. В настоящее время у меня определено несколько разных ViewSet. Что я хотел бы сделать, так это позволить владельцу объекта модели вносить любые изменения, которые он хотел бы в этот объект, но не позволять всем остальным (кроме администраторов) даже просматривать объекты. По сути, мне нужен способ применения классов разрешений к определенным методам, чтобы разрешить только администраторам просматривать «список», владельцам - «обновлять, уничтожать и т. Д.», А аутентифицированным пользователям - «создавать». В настоящее время у меня есть что-то вроде этого:

class LinkViewSet(viewsets.ModelViewSet):
   queryset = Link.objects.all()
   serializer_class = LinkSerializer

с моделью

class Link(models.Model):
   name = models.CharField(max_length=200)
   url = models.URLField()
   # another model with a OneToMany relationship
   section = models.ForeignKey('homepage.LinkSection', related_name='links', on_delete=models.CASCADE
   owner = models.ForeignKey('homepage.UserProfile'), related_name='links', on_delete=models.CASCADE)

и класс разрешений, который я хочу применить

class IsOwner(permissions.BasePermission):
   def has_object_permissions(self, request, view, obj):
      return obj.owner == request.user.userprofile

Я уверен, что этого можно достичь, написав полностью настраиваемые представления, но у меня есть интуиция, что есть более простой способ сделать это, тем более что это, по сути, последнее, что мне нужно сделать, чтобы закончить API. Спасибо за любую помощь и дайте мне знать, если вам понадобится дополнительная информация.


person Eric Groom    schedule 25.08.2017    source источник


Ответы (1)


Мне удалось создать класс разрешений, проверив, какое действие использовалось в представлении, как показано ниже:

class IsOwner(permissions.BasePermission):
'''
Custom permission to only give the owner of the object access
'''
message = 'You must be the owner of this object'

def has_permission(self, request, view):
    if view.action == 'list' and not request.user.is_staff:
        print('has_permission false')
        return False
    else:
        print('has_permission true')
        return True

def has_object_permission(self, request, view, obj):
    print('enter has_object_permission')
    # only allow the owner to make changes
    user = self.get_user_for_obj(obj)
    print(f'user: {user.username}')
    if request.user.is_staff:
        print('has_object_permission true: staff')
        return True
    elif view.action == 'create':
        print('has_object_permission true: create')
        return True
    elif user == request.user:
        print('has_object_permission true: owner')
        return True # in practice, an editor will have a profile
    else:
        print('has_object_permission false')
        return False

def get_user_for_obj(self, obj):
    model = type(obj)
    if model is models.UserProfile:
        return obj.user
    else:
        return obj.owner.user

get_user_for_obj предназначен специально для моей реализации в качестве вспомогательного метода, поскольку моя модель несовместима с тем, как получить экземпляр пользователя. Вы не хотите делать has_permission слишком ограничивающим, потому что has_object_permission будет выполняться только в том случае, если has_permission вернет True или если метод не переопределен.

person Eric Groom    schedule 26.08.2017