Разрешить Любые разрешения, необходимые для запросов DELETE в DRF? - PullRequest
0 голосов
/ 31 октября 2018

Я ищу уточнения здесь.

Я создал приложение реагирования, которое подключается к Django Rest Framework (DRF). Приложение полностью закрытое, что означает, что никто, не прошедший проверку подлинности, не может ничего сделать Для этого я использовал TokenAuthentication (сейчас, потому что я думаю, что SessionAuthentication будет более безопасным).

Я изо всех сил пытаюсь понять это:

  • Я могу аутентифицироваться и установить соответствующий заголовок (Авторизация) с помощью моего токена.
  • Я могу выполнять запросы GET / POST / PATCH без проблем
  • однако: УДАЛИТЬ запросы не работают: я получаю 401 - Несанкционированная ошибка. Но мой заголовок с моим токеном в порядке. Я использую запросы DELETE для удаления объектов из моей базы данных.

Я нашел способ заставить его работать: украсив мой класс вида @permission_classes((AllowAny, )), он просто отлично работает. Но я не доволен этим.

Итак, почему это?

В моем файле настроек у меня есть:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated', )
}

В документации DRF ( ссылка ) написано:

Для запросов DELETE требуется, чтобы у пользователя было разрешение на удаление модели.

Но мой пользователь - администратор, так зачем мне явно добавлять этот декоратор?

Что я делаю не так? Это не может быть лучшим способом сделать это. И почему он работает хорошо без декоратора, если я делаю запрос с внешним клиентом API (например, Postman - я использую Paw) ??

Для справки, мой упрощенный класс просмотра:

@permission_classes((AllowAny, ))
class ObservationAPIView(APIView):

    def delete(self, request, test_id, observation_id, format=None):

        # see if my object exists
        try:
            obs_object_to_delete = Observation.objects.get(pk=observation_id)
            test_obj = Test.objects.get(pk=test_id)

        except ObjectDoesNotExist:
            errormsg = {
                'observation id': observation_id,
                'test id': test_id,
                'message': 'Cannot delete this object. Observation ID or test ID not found.'
            }
            return Response(errormsg, status=status.HTTP_404_NOT_FOUND)

        # it exists, delete it 
        obs_object_to_delete.delete()

        # return the test data (not the deleted object)
        serializer = TestSerializer(test_obj, many=False)
        return Response(serializer.data)

    def patch(self, request, test_id, observation_id, format=None):

        # there is also a PATCH function to allow for edits. 
        # This does work well without the decorator.

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Нашли это! В URL не было завершающей косой черты, указывающей на метод удаления.

Но вместо того, чтобы выдавать ошибку 404 или что-то еще, DRF ответил ошибкой 401 (неавторизованным). Это заставило меня искать ошибки в авторизации.

Но все еще озадачен этим: установив декоратор @permission_classes ((AllowAny,)), косая черта, как представляется, не обязательна для продолжения работы моего интерфейса после предполёта. Без декоратора (и, соответственно, с правильными разрешениями) React не хочет продолжать работу после предварительной проверки. Если вы добавите косую черту в URL, все будет работать нормально. и так, что здесь происходит? Разрешает ли AnyAn обойти CORS? И требует ли CORS конечные косые черты?

Если кто-то сможет объяснить мне это поведение, я был бы очень признателен.

Спасибо, что посмотрели всех!

0 голосов
/ 01 ноября 2018

Почему это происходит?
Поскольку вы добавили DEFAULT_PERMISSION_CLASSES глобально, (в settings) DRF будет использовать это в каждом представлении на основе классов .

Если вы хотите использовать дополнительные / пользовательские классы разрешений для определенного представления, вы можете добавить его в класс представления с помощью атрибута permission_classes as,

class SampleView(APIView):
    <b>permission_classes = (MyCustomPermissionClass,)</b>
    ....

В вашем случае, вам необходимо override поведение по умолчанию для определенного метода .

Итак, как переопределить классы разрешений по умолчанию для метода partiluar DRF способом?
Класс APIView - метод get_permissions(), который обрабатывает это

class SampleView(APIView):
    <b>def get_permissions(self):
        if self.request.method == 'DELETE':
            return [permission() for permission in (AllowAny,)]
        return super(SampleView, self).get_permissions()</b>
    # your code
...