#python #django-rest-framework #django-permissions
#python #django-rest-framework #django-разрешения
Вопрос:
У меня есть объект note, к которому можно получить доступ из notes/{pk} . Если метод GET или метод только для чтения, я должен был разрешить любому доступ к заметке, если заметка общедоступна ( note.is_private = False
)
Я реализовал это как:
@api_view(['GET', 'DELETE', 'PUT'])
def detail_notes(request, pk):
try:
note = Note.objects.get(pk=pk)
except Note.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
response = NoteSerializer(note)
return Response(response.data)
...
Если метод УСТАНОВЛЕН или УДАЛЕН, я хочу разрешить доступ к заметке, только если текущий пользователь является владельцем заметки. Я реализовал это разрешение (согласно документам) следующим образом:
class IsOwnerOrIsPublic(BasePermission):
def has_object_permission(self, request, view, obj):
user = obj.user
privacy = obj.is_private
if request.method in SAFE_METHODS:
return not privacy # is the note public and is this a read only request ?
return request.user == obj.user
Однако, когда я добавляю @permission_classes([IsOwnerOrIsPublic])
декоратор в свое представление, разрешение не ограничивает доступ к неавторизованному пользователю. Я могу просмотреть любую заметку с помощью pk.
Я попытался явно вызвать IsOwnerOrIsPublic.has_object_permissions(), на мой взгляд, с этим кодом:
authorized = IsOwnerOrIsPublic.has_object_permission(request, note)
if not authorized:
return Response(status=HTTP_401_UNAUTHORIZED)
Но я получаю ошибку has_object_permission() missing 2 required positional arguments: 'view' and 'obj'
(очевидно), и я не знаю, какие еще аргументы передать. Например, что такое аргумент view?
Как мне заставить это разрешение работать с этим представлением? В качестве альтернативы, как мне заставить это ограничение работать?
Ответ №1:
Обратите внимание, что мое решение основано на общих представлениях, которые проще реализовать. Попробуйте использовать следующий класс представления:
from rest_framework import generics
from django.shortcuts import get_object_or_404
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
...
# generics.RetrieveUpdateDestroyAPIView will allow Get, put, delete
class NoteDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
"""
Retrieve, update, or delete note by its author
Retrieve only for readers
"""
# I'll assume you are using token authentication
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated, IsOwnerOrIsPublic,)
serializer_class = NoteSerializer
def get_object(self):
note = get_object_or_404(Note, pk=self.kwargs['pk'])
self.check_object_permissions(self.request, note)
return note