2016-11-01 3 views
1

В настоящее время я преобразовываю все свои представления в generics, так как мне нравится, как очищается код. Я пытаюсь сделать мой взгляд пользователя детали, например, так:Разрешения Django Rest Framework не вызываются

# User.views 

from Common import view_mixins, view_filters, view_permissions 

class UserDetail(view_mixins.IntOrStrLookupMixin, generics.RetrieveUpdateDestroyAPIView): 
    queryset = Profile.objects.all() 

    lookup_fields = ('user__pk', 'user__username') 
    lookup_url_kwarg = 'userid' 

    filter_backends = (view_filters.ResourceVisibilityFilter,) 
    permission_classes = (view_permissions.IsOwnerOrReadOnly,) 

    serializer_class = ProfileSerializer 

    def update(self, request, *args, **kwargs): 
     user = self.get_object() 
     return Response('whatever') 

# Common.view_permissions 

SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS') 

class IsOwnerOrReadOnly(permissions.BasePermission): 
    ''' 
    Owner of object can GET, PUT, DELETE. Everyone else can GET. 
    ''' 

    def has_permission(self, request, view): 
     return True 

    def has_object_permission(self, request, view, obj): 
     print('did you call me?') 
     return (
      request.method in SAFE_METHODS 
      or 
      obj.user == request.user 
     ) 

# Common.view_mixins 

class IntOrStrLookupMixin(object): 
    """ 
    Apply to views that can be looked up by slug or pk 
    """ 
    def get_object(self): 
     queryset = self.get_queryset() 
     queryset = self.filter_queryset(queryset) 

     filter = {} 

     for field in self.kwargs: 
      argument = self.kwargs[field] 

      if is_int(argument): 
       filter[self.lookup_fields[0]] = argument 
      else: 
       filter[self.lookup_fields[1]] = argument 

     return get_object_or_404(queryset, **filter) 

Так что мой вопрос не будет, разрешение не называется. Я могу получить пользователя в порядке, но каждый может сделать PUT или DELETE, на которых я пытаюсь предотвратить.

+1

Хотя ответа не существует ... Когда я сталкиваюсь с подобными проблемами в DRF, я благодарен за http://www.cdrf.co. Удивительный удивительный ресурс, который позволяет вам легко вникать в исходный код и быстро просматривать, как каждый бит работает вместе. –

+0

Вау! Это супер полезно! Спасибо огромное! –

ответ

0

Я думаю, что столкнулся с этой проблемой. Разрешения уровня объекта вызывается только при использовании метода get_object() для получения объекта. Обновите обновление() с помощью этой строки, и вы увидите разрешения, вызываемые. И обновить пользовательские get_object() либо вызвать супер метод или вызов разрешения непосредственно

 
class UserDetail(view_mixins.IntOrStrLookupMixin, generics.RetrieveUpdateDestroyAPIView): 
    ... blah blah blah 
    def update(self, request): 
     user = self.get_object() 
     return Response('whatever') 

class IntOrStrLookupMixin(object): 
    def get_object(self): 
     ... retrieve the object ... 
     self.check_object_permissions(self.request, obj) 
     return obj 

Edit: Я подал отчет об ошибке по этому поводу с командой ФПИ и они обновили документацию. На странице разрешений в документах говорится: «Разрешения уровня объекта выполняются в общих представлениях среды REST, когда вызывается .get_object()». Я согласен, что это довольно тонкая вещь, и ее легко пропустить.

Редактировать # 2: Похоже, проблема заключается не только в обновлении(), не вызывающем get_object(), но также в методе IntOrStrLookupMixin, переопределяющем метод get_object(). Обновлен код для отражения

+0

Все еще ничего. :/ –

+0

К сожалению, я имел в виду, чтобы вы обновили свой класс просмотра, а не ваш класс разрешений. Обновил код в моем ответе. –

+0

Да ничего. Я могу отредактировать пользователя от другого пользователя и «вы мне позвонили?» никогда не печатается на консоли. –

0

В моем миксе, мне пришлось вызвать метод check_object_permissions.

class IntOrStrLookupMixin(object): 
    """ 
    Apply to views that can be looked up by slug or pk 
    """ 
    def get_object(self): 
     queryset = self.get_queryset() 
     queryset = self.filter_queryset(queryset) 

     filter = {} 

     for field in self.kwargs: 
      argument = self.kwargs[field] 

      if is_int(argument): 
       filter[self.lookup_fields[0]] = argument 
      else: 
       filter[self.lookup_fields[1]] = argument 

     obj = get_object_or_404(queryset, **filter) 
     self.check_object_permissions(self.request, obj) 

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