2016-05-23 3 views
1

У меня есть базовое приложение, в котором есть пользователи и задачи, и я хочу, чтобы TaskDetails был доступен только владельцу. Взгляды, права доступа и настройки являются следующие:Django REST Framework: разрешения на уровне объектов не работают в соответствии с учебным пособием

views.py:

from cardinal.permissions import IsOwner 

class TaskDetail(generics.RetrieveUpdateDestroyAPIView): 
    queryset = Task.objects.all() 
    serializer_class = TaskSerializer 
    permissions_classes = (permissions.IsAuthenticatedOrReadOnly, 
          IsOwner) 

permissions.py:

from rest_framework import permissions 


class IsOwnerOrReadOnly(permissions.BasePermission): 
    def has_object_permission(self, request, view, obj): 
     print("Hit IsOWnerOrReadOnly") 
     if request.method in permissions.SAFE_METHODS: 
      return True 

     return obj.owner == request.user 


class IsOwner(permissions.BasePermission): 
    def has_object_permission(self, request, view, obj): 
     print("Hit IsOwner") 
     return obj.owner == request.user 


class IsUser(permissions.BasePermission): 
    def has_object_permission(self, request, view, obj): 
     print("Hit IsUser") 
     return obj.username == request.user.username 

settings.py:

REST_FRAMEWORK = { 
    # 'DEFAULT_PERMISSION_CLASSES': (
    #  'rest_framework.permissions.IsAuthenticated', 
    #  'rest_framework.permissions.IsAuthenticatedOrReadOnly', 
    #  'cardinal.permissions.IsOwnerOrReadOnly', 
    #  'cardinal.permissions.IsOwner', 
    #), 
    'DEFAULT_AUTHENTICATION_CLASSES': (
     'rest_framework.authentication.SessionAuthentication', 
     'rest_framework.authentication.BasicAuthentication', 
     'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 
    ), 
} 

Когда я логин как «Боб», я могу получить доступ к задачам «Susi», и разрешения не срабатывают. Когда я отказываюсь от комментариев по умолчанию в настройках, все работает правильно, но я не хочу устанавливать каждое разрешение, которое я пишу, как «Default» для его работы.

Я посмотрел на некоторые другие ответы и один предложил переопределение метода get_object в пределах TaskDetail Вид с:

def get_object(self): 
    obj = get_object_or_404(self.get_queryset()) 
    self.check_object_permissions(self.request, obj) 
    return obj 

Когда я попробовал это, я получаю ошибку:

get() returned more than one Task -- it returned 7! 

Как я сделать так, чтобы разрешения на уровне объекта использовались должным образом, не устанавливая их в настройках по умолчанию?

обновление

Не знаю, как и почему, но я получил его на работу, импортируя все приложение и указав полный путь.

import cardinal 

class TaskDetail(generics.RetrieveUpdateDestroyAPIView): 
    queryset = Task.objects.all() 
    serializer_class = TaskSerializer 
    permission_classes = (cardinal.permissions.IsOwner,) 

ответ

0

У вас есть две проблемы в вашем коде:

Во-первых, ошибка в том, что вы передаете QuerySet более одного объекта (Task.objects.all()) в get_object_or_404 без указания одного конкретного рк. See the third example of this section в документах.

Во-вторых, вам нужно поднять ошибку, если проверка разрешения не возвращает true. Прямо сейчас вы проверяете разрешение, но возвращаете ли оно True или False не влияет на код.

Одно решения сделать что-то вроде следующего, предполагая ваши DetailView «ы привязок имеют pk kwarg (если он отличается, замените изменённые kwarg):

def get_object(self): 
    obj = get_object_or_404(self.get_queryset(), pk=self.kwargs.get('pk')) 
    if self.check_object_permissions(self.request, obj): 
     return obj 
    else: 
     raise Http404() 
+0

Я опробовал этот фрагмент кода, и теперь всякий раз, когда Я перехожу к TaskDetail, он возвращает «деталь»: «Не найден. Я помещаю в него какие-то заявления печати, и он попадает в предложение else, но никогда не ударяет по разрешению IsOwner для какой-либо задачи. Любая идея? –

+0

@KyleTruong It звучит так: 'get_object_or_404' возвращает 404, это ответ по умолчанию от этой функции, когда объект не найден. – YPCrumble

+1

Насколько я могу судить,' self.check_object_permissions (s elf.request, obj) 'метод ничего не возвращает. Следовательно, его нужно просто называть. При необходимости он будет поднимать исключение. В противном случае переходите. – onekiloparsec

Смежные вопросы