Глубокое погружение во все, что вам нужно знать о представлениях Django REST Framework с модульным тестированием.

Django — один из самых популярных фреймворков на Python. Он помогает вам с легкостью создавать веб-приложения, поставляется с множеством встроенных функций, отличным сообществом, которое поможет вам, а также другими вспомогательными библиотеками/инструментами, чтобы уменьшить вашу боль в шее. Одной из таких библиотек является Django REST framework (DRF). Этомощный и гибкий набор инструментов для создания веб-API поверх Django.

Область применения этой серии руководств и то, чем она не является

В этой серии руководств мы рассмотрим только классы представлений, которые мы можем использовать при создании серверной части веб-приложений с использованием DRF. Это НЕ руководство для начинающих по DRF или Django. Я предполагаю, что у вас есть средний уровень понимания Python и Django. При объяснении некоторых концепций я мог бы рассказать о сериализаторах, моделях и аутентификации/авторизации, но я не буду углубляться в эти темы, поскольку для них требуется отдельный набор руководств. Это все о представлениях DRF.

Конечная цель

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

Мы НЕ будем создавать сквозное веб-приложение, но мы будем использовать сценарии, когда это необходимо, для понимания концепций.

Мы также рассмотрим, как мы можем протестировать наш код, используя собственные инструменты тестирования Django, а также pytest.

Что вообще такое «просмотры»?

Django следует шаблону Mmodel-Vview-Ccontroller достаточно точно, чтобы его можно было назвать фреймворком MVC, но он называет View as Templates и Controller as Views (сбивает с толку? Посмотрите здесь), поэтому MTV.

В Django View (MTV) описывает данные, которые представляются пользователю. Дело не в том, как выглядят данные, а в том, какие данные представлены, т. е. они описывают какие данные вы видите, а не как вы видите это. О части как вы это видите заботятся шаблоны T. Таким образом, в Django представление — это функция, которая получает запрос для конкретной конечной точки URL. Эта функция обратного вызова отвечает за обработку входящего запроса и отправку соответствующего ответа. Для дальнейшего чтения проверьте официальную документацию.

Просмотры DRF

Django REST Framework (DRF) построен на основе Django, поэтому он наследует от него множество функций. Классы представлений, доступные в DRF, унаследованы от класса Django View. Из всех различных классов представлений, которые мы получаем из DRF, класс APIView является основным, так как два других класса представлений наследуются от него.

APIView — Обзор

APIView обеспечивает наименьшую степень абстракции из трех классов представлений. Таким образом, у вас есть большая свобода настраивать его в соответствии с вашими потребностями, но это означает, что вам также нужно написать гораздо больше кода. Это хороший выбор, если вам нужно иметь большой контроль над представлениями. Здесь вы должны написать каждую бизнес-логику самостоятельно. Здесь вы получаете методы класса, такие как get(), post(), patch() и т. д., которые сопоставляются с соответствующим методом HTTP.

Все входящие запросы передаются подходящим методам с помощью DRF APIView . Веб-запросы, передаваемые методам обработчика, будут экземплярами Request REST framework, а не экземплярами HttpRequest Django, а ответ, который будет возвращен представлением, будет Responseтипа DRF, а неДжанго HttpResponse .

Слышал, ты любишь «классы»?

В Django REST Framework у нас есть два способа определить наши представления: один основан на классах, а другой основан на функциях. Сначала мы рассмотрим представления на основе классов.

Теперь, если вы пришли из Flask, то вы знакомы с представлениями на основе функций, но в Django предпочтительным способом определения представления является класс. Используя представления на основе классов, мы добиваемся СУХОЙ(Dне Rповторять Yсамих себя). Мы можем повторно использовать наш код намного эффективнее, но это повторное использование стоит нам удобочитаемости нашего кода, поскольку делает нашу реализацию немного более сложной.

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

models.py должен выглядеть так:

Наш serializers.py должен выглядеть так:

Наш views.py должен выглядеть так:

Наконец, urls.py:

Как видите, мы определяем методы для всех типов запросов, которые мы хотим разрешить для этой конечной точки.

В нашем views.py мы переопределяем две переменные класса, authentication_classes и permission_classes, они называются атрибутами политики. Они используются для изменения настроек нашего класса представления.

Всего у нас есть шесть атрибутов политики в APIView,

  • renderer_classes: используется для передачи набора классов средства визуализации, которые можно использовать для визуализации конечной точки.
  • parser_classes: определяет, какие анализаторы данных разрешены для разных типов мультимедиа.
  • authentication_classes: чтобы установить схемы аутентификации, которые мы хотим использовать в представлении.
  • Throttle_classes: определяет, должен ли запрос авторизоваться на основе скорости запросов.
  • permission_classes: Какой класс разрешений использовать, чтобы определить, авторизован ли пользователь для доступа к представлению.
  • content_negotiation_class: выбирает одно из нескольких возможных представлений ресурса для возврата клиенту.

За кулисами

Теперь давайте посмотрим, как на самом деле работают представления DRF.

После попадания по URL-адресу запрос переходит к связанному с ним классу представления, например, если запрошенная конечная точка /api/v1/posts/, класс представления, связанный с этим URL-адресом, будет получен из urls.py, поэтому запрос будет перенаправлено PostListView .

Теперь, когда запрос достигает соответствующего класса представления, класс затем инициализирует новый объект Request (не HttpRequest ). Функция DRF Request дает нам гораздо больше функциональных возможностей, чем нативная HttpRequest Django. Он поддерживает почти все распространенные методы HTTP. Объекты RequestREST framework обеспечивают гибкий анализ запросов, который позволяет нам обрабатывать запросы с данными JSON или другими типами мультимедиа так же, как мы обычно работаем с данными формы.

Мы можем получить доступ к проанализированному содержимому тела запроса, используя request.data. Он поддерживает как файловые, так и нефайловыевходные данные.

Как только входящий запрос сохраняется в request ,DRF выполняет необходимые методы аутентификации и авторизации. Мы можем изменить способ его выполнения и создать собственный класс Auth, но это тема для другого дня.

Теперь, когда часть аутентификации выполнена, она проверит, поддерживается ли входящий HTTP-метод DRF и определен ли в классе представления, если нет, то будет возбуждено исключение MethodNotAllowed. Например, если мы запросим PATCH, это исключение будет вызвано, поскольку мы не определили метод patch() в PostListView . За это отвечает dispatch().

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

Класс слишком много? Давайте попробуем представления на основе функций

Если вы не хотите писать классы для представлений, вы также можете написать отдельные функции. Если вы пишете представление в виде функции, вам нужно использовать декоратор @api_view.

@api_view — это декоратор, который преобразует представление, основанное на функциях в подкласс APIView (таким образом предоставляя классы Response и Request). Он принимает список разрешенных методов для представления в качестве аргумента.

Давайте напишем функциональное представление.

Здесь мы преобразовали get_or_create_post в подкласс APIView с помощью декоратора @api_view. Мы упоминаем методы HTTP, которые мы хотим, чтобы эта конечная точка принимала.

В urls.py измените views.PostListView.as_view() на views.get_or_create_post  и удалите последнюю строку, так как она нам больше не нужна.

В функциональном представлении у нас есть декораторы политик.

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

Тестирование наших представлений

Одной из наиболее важных частей создания программного обеспечения является его тщательное тестирование, чтобы уменьшить количество ошибок, с которыми мы можем столкнуться после его отправки нашим клиентам. Для этого нам нужно иметь хорошие практики TDD при написании нашего программного обеспечения.

Мы не будем тестировать наш код в этом уроке, так как этот пост уже немного длинный. Мы сделаем это во второй части, где мы закончим с основами. Я просто хотел бросить здесь идею TDD.

Заключение

Итак, как мы видели, создавать представления с помощью APIView довольно просто. Здесь у нас было больше свободы при создании наших представлений, если вы не знаете, что это значит, вы поймете это, когда мы начнем использовать Generic Views и ViewSets. Мы встретимся снова во второй части этой серии руководств по общим представлениям.

Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Получите эксклюзивный доступ к возможностям написания и советам в нашем сообществе Discord.