Представления на основе классов

Представления Django, основанные на классах, являются приятным отступлением от представлений старого стиля.

Reinout van Rees

Фреймворк REST предоставляет класс APIView, который является подклассом класса Django View.

Классы APIView отличаются от обычных классов View следующим образом:

  • Запросы, передаваемые методам обработчика, будут экземплярами фреймворка REST Request, а не экземплярами Django HttpRequest.

  • Методы обработчика могут возвращать Response , вместо HttpResponse от Django. Представление будет управлять согласованием содержимого и установкой правильного рендеринга в ответе.

  • Любые исключения APIException будут перехвачены и опосредованы в соответствующие ответы.

  • Входящие запросы будут аутентифицированы, и перед отправкой запроса в метод обработчика будут выполнены соответствующие проверки разрешений и/или дросселирования.

Использование класса APIView практически не отличается от использования обычного класса View, как обычно, входящий запрос отправляется в соответствующий метод-обработчик, такой как .get() или .post(). Кроме того, для класса может быть установлен ряд атрибутов, которые контролируют различные аспекты политики API.

Например:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions
from django.contrib.auth.models import User

class ListUsers(APIView):
    """
    View to list all users in the system.

    * Requires token authentication.
    * Only admin users are able to access this view.
    """
    authentication_classes = [authentication.TokenAuthentication]
    permission_classes = [permissions.IsAdminUser]

    def get(self, request, format=None):
        """
        Return a list of all users.
        """
        usernames = [user.username for user in User.objects.all()]
        return Response(usernames)

Примечание: Полные методы, атрибуты и отношения между APIView , GenericAPIView , различными Mixins , и Viewsets Django REST Framework могут быть изначально сложными. В дополнение к документации, представленной здесь, ресурс Classy Django REST Framework предоставляет просматриваемую ссылку с полными методами и атрибутами для каждого из представлений Django REST Framework, основанных на классах.


Атрибуты политики API

Следующие атрибуты управляют подключаемыми аспектами представлений API.

.renderer_classes

.parser_classes

.authentication_classes

.throttle_classes

.permission_classes

.content_negotiation_class

Методы инстанцирования политики API

Следующие методы используются REST framework для инстанцирования различных подключаемых политик API. Как правило, вам не нужно переопределять эти методы.

.get_renderers(self)

.get_parsers(self)

.get_authenticators(self)

.get_throttles(self)

.get_permissions(self)

.get_content_negotiator(self)

.get_exception_handler(self)

Методы реализации политики API

Перед отправкой в метод обработчика вызываются следующие методы.

.check_permissions(self, request)

.check_throttles(self, request)

.perform_content_negotiation(self, request, force=False)

Методы диспетчеризации

Следующие методы вызываются непосредственно методом .dispatch() представления. Они выполняют любые действия, которые должны произойти до или после вызова методов обработчика, таких как .get() , .post() , put() , patch() и .delete().

.initial(self, request, *args, **kwargs)

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

Обычно вам не нужно переопределять этот метод.

.handle_exception(self, exc)

Любое исключение, выброшенное методом обработчика, будет передано в этот метод, который либо возвращает экземпляр Response, либо повторно вызывает исключение.

Реализация по умолчанию обрабатывает любой подкласс rest_framework.exceptions.APIException , а также исключения Django Http404 и PermissionDenied, и возвращает соответствующий ответ об ошибке.

Если вам нужно настроить ответы на ошибки, которые возвращает ваш API, вам следует подклассифицировать этот метод.

.initialize_request(self, request, *args, **kwargs)

Гарантирует, что объект запроса, передаваемый методу обработчика, является экземпляром Request , а не обычным Django HttpRequest.

Обычно вам не нужно переопределять этот метод.

.finalize_response(self, request, response, *args, **kwargs)

Гарантирует, что любой объект Response, возвращенный из метода обработчика, будет преобразован в правильный тип содержимого, как определено в процессе согласования содержимого.

Обычно вам не нужно переопределять этот метод.


Представления на основе функций

Говорить [что классовые взгляды] всегда являются лучшим решением - это ошибка.

Nick Coghlan

Фреймворк REST также позволяет работать с обычными представлениями, основанными на функциях. Он предоставляет набор простых декораторов, которые оборачивают ваши представления, основанные на функциях, чтобы обеспечить получение экземпляра Request (а не обычного Django HttpRequest ) и позволяют им возвращать Response (а не Django HttpResponse ), а также позволяют вам настроить обработку запроса.

@api_view()

Подпись: @api_view(http_method_names=['GET'])

Ядром этой функциональности является декоратор api_view, который принимает список методов HTTP, на которые должно реагировать ваше представление. Например, вот как можно написать очень простое представление, которое просто вручную возвращает некоторые данные:

from rest_framework.decorators import api_view

@api_view()
def hello_world(request):
    return Response({"message": "Hello, world!"})

Это представление будет использовать рендереры по умолчанию, парсеры, классы аутентификации и т.д., указанные в settings.

По умолчанию принимаются только методы GET. Другие методы будут отвечать «405 Method Not Allowed». Чтобы изменить это поведение, укажите, какие методы допускает представление, например, так:

@api_view(['GET', 'POST'])
def hello_world(request):
    if request.method == 'POST':
        return Response({"message": "Got some data!", "data": request.data})
    return Response({"message": "Hello, world!"})

Декораторы политики API

Чтобы переопределить настройки по умолчанию, REST framework предоставляет набор дополнительных декораторов, которые можно добавить к вашим представлениям. Они должны располагаться после (ниже) декоратора @api_view. Например, чтобы создать представление, которое использует декоратор throttle для обеспечения того, что оно может быть вызвано только один раз в день определенным пользователем, используйте декоратор @throttle_classes, передавая список классов дросселей:

from rest_framework.decorators import api_view, throttle_classes
from rest_framework.throttling import UserRateThrottle

class OncePerDayUserThrottle(UserRateThrottle):
    rate = '1/day'

@api_view(['GET'])
@throttle_classes([OncePerDayUserThrottle])
def view(request):
    return Response({"message": "Hello for today! See you tomorrow!"})

Эти декораторы соответствуют атрибутам, установленным на подклассах APIView, описанных выше.

Доступными декораторами являются:

  • @renderer_classes(...)

  • @parser_classes(...)

  • @authentication_classes(...)

  • @throttle_classes(...)

  • @permission_classes(...)

Каждый из этих декораторов принимает один аргумент, который должен быть списком или кортежем классов.

Декоратор схемы представления

Чтобы отменить генерацию схемы по умолчанию для представлений, основанных на функциях, вы можете использовать декоратор @schema. Он должен располагаться после (ниже) декоратора @api_view. Например:

from rest_framework.decorators import api_view, schema
from rest_framework.schemas import AutoSchema

class CustomAutoSchema(AutoSchema):
    def get_link(self, path, method, base_url):
        # override view introspection here...

@api_view(['GET'])
@schema(CustomAutoSchema())
def view(request):
    return Response({"message": "Hello for today! See you tomorrow!"})

Этот декоратор принимает один экземпляр AutoSchema, экземпляр подкласса AutoSchema или экземпляр ManualSchema, как описано в Schemas documentation. Вы можете передать None для того, чтобы исключить представление из генерации схемы.

@api_view(['GET'])
@schema(None)
def view(request):
    return Response({"message": "Will not appear in schema!"})
Вернуться на верх