Должны ли authentication_classes и permission_classes в представлениях Django REST Framework быть определены с помощью списков или кортежей?

Я пытаюсь понять, как лучше всего задавать authentication_classes и permission_classes в APIView Django REST Framework. В частности, я видел, что для определения этих атрибутов используются как кортежи, так и списки:

Использование кортежа:

class Home(APIView):
    authentication_classes = (JWTAuthentication,)
    permission_classes = (permissions.IsAuthenticated,)

Использование списка:

class Home(APIView):
    authentication_classes = [JWTAuthentication]
    permission_classes = [permissions.IsAuthenticated]

Похоже, оба подхода работают корректно, но я не уверен, что есть какие-то конкретные причины предпочесть один из них другому. Следует ли мне использовать список или кортеж в этом сценарии? Есть ли какие-либо последствия использования одного или другого с точки зрения производительности, читабельности или следования лучшим практикам Django REST Framework?

Я пробовал использовать как кортежи, так и списки для authentication_classes и permission_classes в APIView Django REST Framework. Оба варианта работают хорошо, но я не уверен, какой из них лучше или рекомендуется. Я ожидал найти четкое руководство по этому вопросу.

Оба варианта работают эквивалентно. Документация Django REST Framework, похоже, предпочитает списки, так что, возможно, следует использовать списки.

class ListUsers(APIView):
    authentication_classes = [authentication.TokenAuthentication]
    permission_classes = [permissions.IsAdminUser]

Сначала я объясню процесс выполнения аутентификации в DRF.

class APIView(View):
    def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)

        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

Функцией, которая фактически выполняет аутентификацию в DRF, является функция perform_authentication, но до этого, когда метод initialize_request создает объект запроса, он вызывает метод get_authenticators и передает его в качестве аргумента.

class APIView(View):
    ...
    def get_authenticators(self):
        """
        Instantiates and returns the list of authenticators that this view can use.
        """
        return [auth() for auth in self.authentication_classes]
    ...

Здесь функция get_authenticators повторяет переменную authentication_classes, определенную в View, созданной пользователями, чтобы создать и вернуть каждый объект класса аутентификации.

В этом процессе используется переменная authentication_classes, определенная вопрошающим.

Как видно из приведенного выше кода, это должен быть повторяющийся объект, поскольку он используется в операторе for. Вот почему разрешены упорядочивания и кортежи.

Проверка разрешения одинакова.

class APIView(View):
    def dispatch(self, request, *args, **kwargs):
        ...
        try:
            self.initial(request, *args, **kwargs)

    def initial(self, request, *args, **kwargs):
        ...
        self.check_permissions(request)
        ...

    def check_permissions(self, request):
        for permission in self.get_permissions():
            if not permission.has_permission(request, self):
        ...

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        return [permission() for permission in self.permission_classes]

Процесс проверки разрешений в DRF APIView выглядит следующим образом.

Значение permissions_classes, установленное пользователем, используется в методе get_permissions и выполняет тот же процесс аутентификации, что и ранее.

То есть, поскольку permissions_classes или authentication_classes должны использоваться в повторениях, именно поэтому вы должны использовать массив или кортеж этих проблемных типов данных.

Причина, по которой DRF реализовала вышеуказанную логику для разрешений и аутентификации, заключается в возможности использования множественной аутентификации и разрешений.

Сразу к делу: работают как tuple, так и list. В принципе, если вы хотите изменить переменную, то используйте списки. Если вы конкретно не хотите и не желаете, чтобы кто-то изменял переменную, то используйте кортежи. Это просто проблема неизменяемости против изменяемости.

Вернуться на верх