Django: ViewSets не принимает требуемый вход в систему, выдача SessionAuthentication бесполезна - PullRequest
2 голосов
/ 07 мая 2020

У меня проблемы с использованием DRF SessionAuthentication с представлениями, определенными как ModelViewSets. «LoginRequiredMixin» отлично работает в общих представлениях, но мне они действительно не нравятся, поскольку они требуют, чтобы я определял все URL-адреса вручную и устанавливал их в правильном порядке. Очень утомительно, когда ViewSets позволяют вам определять маршруты более аккуратно. но он этого не принимает. Пробовали указать authentication_class SessionAuthentication в моем ViewSet, но безрезультатно, следуя этим сообщениям:

Текущий файл FooBar_views.py. Единственный способ убедиться, что пользователь аутентифицирован, - это проверить его JWT, указанный в заголовках его HTTP-запроса.

foobar_vews.py with ViewSets

# @login_required not being accepted when imported
class FooBarViewSet(viewsets.ModelViewSet):
    """
    Foo Bar ViewSet calling various serializers depending on request type (GET, PUT etc.)
    """

    # Trying to filter FooBars list by status: Exluding unwanted ones
    queryset = FooBar.objects.exclude(status__name = 'SOLD').exclude(status__name = 'DELETED').order_by('id').reverse()

    # mapping serializer into the action
    serializer_classes = {
        'list': FooBarIndexSerializer,
        'retrieve': FooBarDetailsSerializer,
        'create': FooBarCreateSerializer,
    }

    # Your default serializer
    default_serializer_class = FooBarIndexSerializer

    def get_serializer_class(self):
        """
        Method to detect request type (GET, PUT etc.) and select corresponding serializer.
        """
        return self.serializer_classes.get(self.action, self.default_serializer_class)

    # TODO: Move this to the permissions.py file?
    def get_permissions(self):
        """
        Method to apply permissions depending on request type (GET, PUT etc.)
        """
        if self.request.method == 'GET':
            return [permissions.DjangoModelPermissionsOrAnonReadOnly()]
        elif self.request.method == 'POST':
            return [permissions.IsAuthenticated(), IsArtist()]
        else:  # PUT, PATCH, DELETE
            return [permissions.IsAuthenticated(), IsOwner()]

Эквивалент I Необходимо определить, используются ли общие представления. Как видно, мне не нужно добавлять какой-либо класс разрешений isAuthenticated, поскольку LoginRequiredMixin проверяет, что пользователь вошел в систему, проверяя sessionId и CSRFToken.

Проблема здесь, мне нужно вручную определить все соответствующие URL-адреса в файле url.py. Это утомительно и сбивает с толку, поскольку FooBarListView и FooBarCreateView обычно должны быть одним и тем же URL-адресом, но разные запросы выполняются как GET и POST.

foobar_vews.py with generic views

class FooBarListView(LoginRequiredMixin, ListAPIView):
   queryset = FooBar.objects.all()
   serializer_class = FooBarIndexSerializer

class FooBarDetailView(LoginRequiredMixin, RetrieveAPIView):
   queryset = FooBar.objects.all()
   serializer_class = FooBarDetailsSerializer

# TODO: Voir pour passer aux modelViews
class FooBarCreateView(LoginRequiredMixin, CreateAPIView):
   queryset = FooBar.objects.all()
   serializer_class = FooBarCreateSerializer
   permission_classes = [IsOwner]

   def perform_create(self, serializer):
       user=self.request.user
       serializer.save(user=user)

class FooBarUpdateDestroyView(LoginRequiredMixin, UpdateDestroyAPIView):
   queryset=FooBar.objects.all()
   serializer_class = FooBarDetailsSerializer
   permission_classes = [IsOwner]

Следовательно, существует ли способ проверить, что пользователь отключен в ViewSets, или я вынужден использовать систему аутентификации JWT, сохранять токены на стороне клиента (это даже безопасно?), а из внешнего интерфейса убедитесь, что для каждого запроса пользователь предоставляет эти в заголовках?

Приветствуется любая помощь в том, как реализовать это в ViewSets.

1 Ответ

1 голос
/ 08 мая 2020

Первое: Вы должны понимать, что Decorators можно использовать только в функциях, вы не можете использовать его в представлениях на основе классов, как вы это использовали. Итак, очевидно, что django viewset не будет принимать декоратор @login_required.

Итак, вопрос в том, можете ли вы украсить методы класса? ответ: ДА . Вот django документы Украшение класса , в нем говорится:

Чтобы украсить каждый экземпляр представления на основе классов, вам нужно украсить само определение класса. Для этого вы применяете декоратор к методу dispatch () класса.

Метод класса не совсем то же самое, что и отдельная функция, поэтому вы не можете просто применить декоратор функции к метод - сначала вам нужно преобразовать его в декоратор метода. Декоратор method_decorator преобразует декоратор функции в декоратор метода, чтобы его можно было использовать в методе экземпляра. Например:

class ProtectedView(TemplateView):
    template_name = 'secret.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...